404page – your smart custom 404 error page - Version 3.2

Version Description

new feature to send an HTTP 410 error for deleted objects

Download this release

Release Info

Developer petersplugins
Plugin Icon 128x128 404page – your smart custom 404 error page
Version 3.2
Comparing to
See all releases

Code changes from version 3.1 to 3.2

Files changed (3) hide show
  1. 404page.php +1 -1
  2. inc/class-404page.php +274 -3
  3. readme.txt +7 -1
404page.php CHANGED
@@ -9,7 +9,7 @@
9
  * Plugin Name: 404page - your smart custom 404 error page
10
  * Plugin URI: http://petersplugins.com/free-wordpress-plugins/404page/
11
  * Description: Custom 404 the easy way! Set any page as custom 404 error page. No coding needed. Works with (almost) every Theme.
12
- * Version: 3.1
13
  * Author: Peter Raschendorfer
14
  * Author URI: http://petersplugins.com
15
  * Text Domain: 404page
9
  * Plugin Name: 404page - your smart custom 404 error page
10
  * Plugin URI: http://petersplugins.com/free-wordpress-plugins/404page/
11
  * Description: Custom 404 the easy way! Set any page as custom 404 error page. No coding needed. Works with (almost) every Theme.
12
+ * Version: 3.2
13
  * Author: Peter Raschendorfer
14
  * Author URI: http://petersplugins.com
15
  * Text Domain: 404page
inc/class-404page.php CHANGED
@@ -44,7 +44,7 @@ if ( !class_exists( 'PP_404Page' ) ) {
44
  $this->_file = $file;
45
  $this->plugin_name = '404page';
46
  $this->plugin_slug = '404page';
47
- $this->version = '3.1';
48
  $this->get_settings();
49
  $this->load();
50
  }
@@ -62,6 +62,7 @@ if ( !class_exists( 'PP_404Page' ) ) {
62
  $this->settings['404page_fire_error'] = $this->get_404page_fire_error();
63
  $this->settings['404page_force_error'] = $this->get_404page_force_error();
64
  $this->settings['404page_no_url_guessing'] = $this->get_404page_no_url_guessing();
 
65
  $this->settings['404page_native'] = false;
66
  }
67
 
@@ -145,13 +146,22 @@ if ( !class_exists( 'PP_404Page' ) ) {
145
  if ( defined( 'CUSTOMIZR_VER' ) ) {
146
 
147
  // Customizr Compatibility Mode
148
-
149
  // @since 3.1
150
  add_filter( 'body_class', array( $this, 'add_404_body_class_customizr_mode' ) );
 
151
  add_filter( 'tc_404_header_content', array( $this, 'show404title_customizr_mode' ), 999 );
152
  add_filter( 'tc_404_content', array( $this, 'show404_customizr_mode' ), 999 );
153
  add_filter( 'tc_404_selectors', array( $this, 'show404articleselectors_customizr_mode' ), 999 );
154
 
 
 
 
 
 
 
 
 
155
  } elseif ( $this->settings['404page_method'] != 'STD' ) {
156
 
157
  // Compatibility Mode
@@ -165,8 +175,19 @@ if ( !class_exists( 'PP_404Page' ) ) {
165
 
166
  // Standard Mode
167
  add_filter( '404_template', array( $this, 'show404_standard_mode' ), 999 );
 
168
  if ( $this->settings['404page_fire_error'] ) {
 
169
  add_action( 'template_redirect', array( $this, 'do_404_header_standard_mode' ) );
 
 
 
 
 
 
 
 
 
170
  }
171
 
172
  }
@@ -319,7 +340,19 @@ if ( !class_exists( 'PP_404Page' ) ) {
319
  function do_404_header() {
320
  // remove the action so we handle only the first query - no custom queries
321
  remove_action( 'wp', array( $this, 'do_404_header' ) );
322
- status_header( 404 );
 
 
 
 
 
 
 
 
 
 
 
 
323
  nocache_headers();
324
  }
325
 
@@ -454,6 +487,25 @@ if ( !class_exists( 'PP_404Page' ) ) {
454
  }
455
 
456
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
457
  /**
458
  * init admin
459
  */
@@ -470,11 +522,13 @@ if ( !class_exists( 'PP_404Page' ) ) {
470
  register_setting( '404page_settings', '404page_fire_error' );
471
  register_setting( '404page_settings', '404page_force_error' );
472
  register_setting( '404page_settings', '404page_no_url_guessing' );
 
473
  add_settings_field( '404page_settings_404page', __( 'Page to be displayed as 404 page', '404page' ) . '&nbsp;<a class="dashicons dashicons-editor-help" href="' . $this->dc_url . '/#settings_select_page"></a>' , array( $this, 'admin_404page' ), '404page_settings_section', '404page-settings', array( 'label_for' => '404page_page_id' ) );
474
  add_settings_field( '404page_settings_hide', '' , array( $this, 'admin_hide' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_hide' ) );
475
  add_settings_field( '404page_settings_fire', '' , array( $this, 'admin_fire404' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_fire_error' ) );
476
  add_settings_field( '404page_settings_force', '' , array( $this, 'admin_force404' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_force_error' ) );
477
  add_settings_field( '404page_settings_noguess', '' , array( $this, 'admin_noguess' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_no_url_guessing' ) );
 
478
  add_settings_field( '404page_settings_method', '', array( $this, 'admin_method' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_method' ) );
479
  }
480
 
@@ -577,6 +631,19 @@ if ( !class_exists( 'PP_404Page' ) ) {
577
  }
578
 
579
 
 
 
 
 
 
 
 
 
 
 
 
 
 
580
  /**
581
  * handle the settings field method
582
  */
@@ -705,6 +772,199 @@ if ( !class_exists( 'PP_404Page' ) ) {
705
  }
706
 
707
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
708
  /**
709
  * create the menu entry
710
  */
@@ -907,6 +1167,17 @@ if ( !class_exists( 'PP_404Page' ) ) {
907
  }
908
 
909
 
 
 
 
 
 
 
 
 
 
 
 
910
  /**
911
  * get the id of the 404 page in the current language if WPML or Polylang is active
912
  */
44
  $this->_file = $file;
45
  $this->plugin_name = '404page';
46
  $this->plugin_slug = '404page';
47
+ $this->version = '3.2';
48
  $this->get_settings();
49
  $this->load();
50
  }
62
  $this->settings['404page_fire_error'] = $this->get_404page_fire_error();
63
  $this->settings['404page_force_error'] = $this->get_404page_force_error();
64
  $this->settings['404page_no_url_guessing'] = $this->get_404page_no_url_guessing();
65
+ $this->settings['404page_http410_if_trashed'] = $this->get_404page_http410_if_trashed();
66
  $this->settings['404page_native'] = false;
67
  }
68
 
146
  if ( defined( 'CUSTOMIZR_VER' ) ) {
147
 
148
  // Customizr Compatibility Mode
149
+
150
  // @since 3.1
151
  add_filter( 'body_class', array( $this, 'add_404_body_class_customizr_mode' ) );
152
+
153
  add_filter( 'tc_404_header_content', array( $this, 'show404title_customizr_mode' ), 999 );
154
  add_filter( 'tc_404_content', array( $this, 'show404_customizr_mode' ), 999 );
155
  add_filter( 'tc_404_selectors', array( $this, 'show404articleselectors_customizr_mode' ), 999 );
156
 
157
+ // send http 410 instead of http 404 if requested resource is in trash
158
+ // @since 3.2
159
+ if ( $this->settings['404page_http410_if_trashed'] ) {
160
+
161
+ add_action( 'template_redirect', array( $this, 'maybe_send_410' ) );
162
+
163
+ }
164
+
165
  } elseif ( $this->settings['404page_method'] != 'STD' ) {
166
 
167
  // Compatibility Mode
175
 
176
  // Standard Mode
177
  add_filter( '404_template', array( $this, 'show404_standard_mode' ), 999 );
178
+
179
  if ( $this->settings['404page_fire_error'] ) {
180
+
181
  add_action( 'template_redirect', array( $this, 'do_404_header_standard_mode' ) );
182
+
183
+ }
184
+
185
+ // send http 410 instead of http 404 if requested resource is in trash
186
+ // @since 3.2
187
+ if ( $this->settings['404page_http410_if_trashed'] ) {
188
+
189
+ add_action( 'template_redirect', array( $this, 'maybe_send_410' ) );
190
+
191
  }
192
 
193
  }
340
  function do_404_header() {
341
  // remove the action so we handle only the first query - no custom queries
342
  remove_action( 'wp', array( $this, 'do_404_header' ) );
343
+
344
+ // send http 410 instead of http 404 if requested resource is in trash
345
+ // @since 3.2
346
+
347
+ if ( $this->settings['404page_http410_if_trashed'] && $this->is_url_in_trash( rawurldecode ( ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ) ) ) {
348
+
349
+ status_header( 410 );
350
+
351
+ } else {
352
+
353
+ status_header( 404 );
354
+
355
+ }
356
  nocache_headers();
357
  }
358
 
487
  }
488
 
489
 
490
+ /**
491
+ * send http 410 instead of http 404 in case the requested URL can be found in trash
492
+ * @since 3.2
493
+ */
494
+ function maybe_send_410() {
495
+
496
+ // we don't do anything if there is no 404
497
+ if ( is_404() ) {
498
+
499
+ if ( $this->is_url_in_trash( rawurldecode ( ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ) ) ) {
500
+
501
+ status_header( 410 );
502
+
503
+ }
504
+ }
505
+
506
+ }
507
+
508
+
509
  /**
510
  * init admin
511
  */
522
  register_setting( '404page_settings', '404page_fire_error' );
523
  register_setting( '404page_settings', '404page_force_error' );
524
  register_setting( '404page_settings', '404page_no_url_guessing' );
525
+ register_setting( '404page_settings', '404page_http410_if_trashed' );
526
  add_settings_field( '404page_settings_404page', __( 'Page to be displayed as 404 page', '404page' ) . '&nbsp;<a class="dashicons dashicons-editor-help" href="' . $this->dc_url . '/#settings_select_page"></a>' , array( $this, 'admin_404page' ), '404page_settings_section', '404page-settings', array( 'label_for' => '404page_page_id' ) );
527
  add_settings_field( '404page_settings_hide', '' , array( $this, 'admin_hide' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_hide' ) );
528
  add_settings_field( '404page_settings_fire', '' , array( $this, 'admin_fire404' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_fire_error' ) );
529
  add_settings_field( '404page_settings_force', '' , array( $this, 'admin_force404' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_force_error' ) );
530
  add_settings_field( '404page_settings_noguess', '' , array( $this, 'admin_noguess' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_no_url_guessing' ) );
531
+ add_settings_field( '404page_settings_http410', '' , array( $this, 'admin_http410' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_http410_if_trashed' ) );
532
  add_settings_field( '404page_settings_method', '', array( $this, 'admin_method' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_method' ) );
533
  }
534
 
631
  }
632
 
633
 
634
+ /**
635
+ * handle the settings field to send an http 410 error in case the object is trashed
636
+ * @since 3.2
637
+ */
638
+ function admin_http410() {
639
+
640
+ echo '<p><input type="checkbox" id="404page_http410_if_trashed" name="404page_http410_if_trashed" value="1"' . checked( true, $this->settings['404page_http410_if_trashed'], false ) . '/>';
641
+ echo '<label for="404page_http410_if_trashed" class="check"></label>' . __( 'Send an HTTP 410 error instead of HTTP 404 in case the requested object is in trash', '404page' ) . '&nbsp;<a class="dashicons dashicons-editor-help" href="' . $this->dc_url . '/#settings_maybe_send_http410"></a><br />';
642
+ echo '<span class="dashicons dashicons-info"></span>&nbsp;' . __( 'Check this if you want to inform search engines that the resource requested is no longer available and will not be available again so it can be removed from the search index immediately.', '404page' );
643
+
644
+ }
645
+
646
+
647
  /**
648
  * handle the settings field method
649
  */
772
  }
773
 
774
 
775
+ /**
776
+ * check if the requested url is found in trash
777
+ * @since 3.2
778
+ * based on WP core function url_to_postid()
779
+ */
780
+ function is_url_in_trash( $url ) {
781
+
782
+ global $wp_rewrite;
783
+ global $wp;
784
+
785
+ // First, check to see if there is a 'p=N' or 'page_id=N' to match against
786
+ if ( preg_match( '#[?&](p|page_id|attachment_id)=(\d+)#', $url, $values ) ) {
787
+
788
+ $id = absint( $values[2] );
789
+
790
+ if ( $id ) {
791
+
792
+ if ( 'trash' == get_post_status( $id ) ) {
793
+
794
+ return true;
795
+
796
+ } else {
797
+
798
+ return false;
799
+
800
+ }
801
+
802
+ }
803
+
804
+ }
805
+
806
+ // Check to see if we are using rewrite rules
807
+ $rewrite = $wp_rewrite->wp_rewrite_rules();
808
+
809
+ // Not using rewrite rules, and 'p=N' and 'page_id=N' methods failed, so we're out of options
810
+ if ( empty( $rewrite ) ) {
811
+
812
+ return false;
813
+
814
+ }
815
+
816
+ // Get rid of the #anchor
817
+ $url_split = explode('#', $url);
818
+ $url = $url_split[0];
819
+
820
+ // Get rid of URL ?query=string
821
+ $url_split = explode('?', $url);
822
+ $url = $url_split[0];
823
+
824
+ // Add 'www.' if it is absent and should be there
825
+ if ( false !== strpos( home_url(), '://www.' ) && false === strpos( $url, '://www.' ) ) {
826
+
827
+ $url = str_replace('://', '://www.', $url);
828
+
829
+ }
830
+
831
+ // Strip 'www.' if it is present and shouldn't be
832
+ if ( false === strpos( home_url(), '://www.' ) ) {
833
+
834
+ $url = str_replace('://www.', '://', $url);
835
+
836
+ }
837
+
838
+ // Strip 'index.php/' if we're not using path info permalinks
839
+ if ( !$wp_rewrite->using_index_permalinks() ) {
840
+
841
+ $url = str_replace( $wp_rewrite->index . '/', '', $url );
842
+
843
+ }
844
+
845
+
846
+ if ( false !== strpos( trailingslashit( $url ), home_url( '/' ) ) ) {
847
+
848
+ // Chop off http://domain.com/[path]
849
+ $url = str_replace(home_url(), '', $url);
850
+
851
+ } else {
852
+
853
+ // Chop off /path/to/blog
854
+ $home_path = parse_url( home_url( '/' ) );
855
+ $home_path = isset( $home_path['path'] ) ? $home_path['path'] : '' ;
856
+ $url = preg_replace( sprintf( '#^%s#', preg_quote( $home_path ) ), '', trailingslashit( $url ) );
857
+
858
+ }
859
+
860
+ // Trim leading and lagging slashes
861
+ $url = trim($url, '/');
862
+
863
+ $request = $url;
864
+ $post_type_query_vars = array();
865
+
866
+ foreach ( get_post_types( array() , 'objects' ) as $post_type => $t ) {
867
+
868
+ if ( ! empty( $t->query_var ) ) {
869
+
870
+ $post_type_query_vars[ $t->query_var ] = $post_type;
871
+
872
+ }
873
+ }
874
+
875
+ // Look for matches.
876
+ $request_match = $request;
877
+ foreach ( (array)$rewrite as $match => $query) {
878
+
879
+ // If the requesting file is the anchor of the match, prepend it
880
+ // to the path info.
881
+ if ( !empty( $url ) && ( $url != $request ) && ( strpos( $match, $url ) === 0 ) ) {
882
+
883
+ $request_match = $url . '/' . $request;
884
+
885
+ }
886
+
887
+ if ( preg_match( "#^$match#", $request_match, $matches ) ) {
888
+
889
+ if ( $wp_rewrite->use_verbose_page_rules && preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch ) ) {
890
+
891
+ // This is a verbose page match, let's check to be sure about it.
892
+ if ( ! get_page_by_path( $matches[ $varmatch[1] ] ) ) {
893
+
894
+ continue;
895
+
896
+ }
897
+ }
898
+
899
+ // Got a match.
900
+
901
+ // Trim the query of everything up to the '?'.
902
+ $query = preg_replace( "!^.+\?!", '', $query );
903
+
904
+ // Substitute the substring matches into the query.
905
+ $query = addslashes( WP_MatchesMapRegex::apply( $query, $matches ) );
906
+
907
+ // Filter out non-public query vars
908
+ parse_str( $query, $query_vars );
909
+ $query = array();
910
+
911
+ foreach ( (array) $query_vars as $key => $value ) {
912
+
913
+ if ( in_array( $key, $wp->public_query_vars ) ) {
914
+
915
+ $query[$key] = $value;
916
+
917
+ if ( isset( $post_type_query_vars[$key] ) ) {
918
+
919
+ $query['post_type'] = $post_type_query_vars[$key];
920
+ $query['name'] = $value;
921
+
922
+ }
923
+
924
+ }
925
+
926
+ }
927
+
928
+ // Magic
929
+ if ( isset( $query['pagename'] ) ) {
930
+
931
+ $query['pagename'] .= '__trashed' ;
932
+
933
+ }
934
+
935
+ if ( isset( $query['name'] ) ) {
936
+
937
+ $query['name'] .= '__trashed' ;
938
+
939
+ }
940
+
941
+ $query['post_status'] = array( 'trash' );
942
+
943
+ // Resolve conflicts between posts with numeric slugs and date archive queries.
944
+ $query = wp_resolve_numeric_slug_conflicts( $query );
945
+
946
+ // Do the query
947
+ $query = new WP_Query( $query );
948
+
949
+ if ( $query->found_posts == 1 ) {
950
+
951
+ return true;
952
+
953
+ } else {
954
+
955
+ return false;
956
+
957
+ }
958
+
959
+ }
960
+
961
+ }
962
+
963
+ return false;
964
+
965
+ }
966
+
967
+
968
  /**
969
  * create the menu entry
970
  */
1167
  }
1168
 
1169
 
1170
+ /**
1171
+ * do we have to send an http 410 error in case the object is in trash?
1172
+ * @since 3.2
1173
+ */
1174
+ private function get_404page_http410_if_trashed() {
1175
+
1176
+ return (bool)get_option( '404page_http410_if_trashed', false );
1177
+
1178
+ }
1179
+
1180
+
1181
  /**
1182
  * get the id of the 404 page in the current language if WPML or Polylang is active
1183
  */
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: http://petersplugins.com/make-a-donation/
4
  Tags: page, 404, error, error page, 404 page, page not found, page not found error, 404 error page, missing, broken link, template, 404 link, seo, custom 404, custom 404 page, custom 404 error, custom 404 error page, customize 404, customize 404 page, customize 404 error page
5
  Requires at least: 3.0
6
  Tested up to: 4.8
7
- Stable tag: 3.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -115,6 +115,9 @@ The 404page plugin adds a CSS class `error404` to the `<body>` tag which can be
115
 
116
  == Changelog ==
117
 
 
 
 
118
  = 3.1 (2017-07-24) =
119
  * bugfix for Polylang ([See Topic](https://wordpress.org/support/topic/3-0-breaks-polylang-support/))
120
  * bugfix for CLI ([See Topic](https://wordpress.org/support/topic/uninstall-php-from-cli-failed/))
@@ -196,6 +199,9 @@ The 404page plugin adds a CSS class `error404` to the `<body>` tag which can be
196
 
197
  == Upgrade Notice ==
198
 
 
 
 
199
  = 3.1 =
200
  fixed two bugs, plus further enhancements
201
 
4
  Tags: page, 404, error, error page, 404 page, page not found, page not found error, 404 error page, missing, broken link, template, 404 link, seo, custom 404, custom 404 page, custom 404 error, custom 404 error page, customize 404, customize 404 page, customize 404 error page
5
  Requires at least: 3.0
6
  Tested up to: 4.8
7
+ Stable tag: 3.2
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
115
 
116
  == Changelog ==
117
 
118
+ = 3.2 (2017-10-05) =
119
+ * new feature to send an HTTP 410 error for deleted objects
120
+
121
  = 3.1 (2017-07-24) =
122
  * bugfix for Polylang ([See Topic](https://wordpress.org/support/topic/3-0-breaks-polylang-support/))
123
  * bugfix for CLI ([See Topic](https://wordpress.org/support/topic/uninstall-php-from-cli-failed/))
199
 
200
  == Upgrade Notice ==
201
 
202
+ = 3.2 =
203
+ new feature to send an HTTP 410 error for deleted objects
204
+
205
  = 3.1 =
206
  fixed two bugs, plus further enhancements
207