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

Version Description

new features added to force 404 error after loading page and to disable URL autocorrection guessing, plus further enhancements

Download this release

Release Info

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

Code changes from version 2.5 to 3.0

404page.js DELETED
@@ -1,20 +0,0 @@
1
- jQuery(document).ready(function($) {
2
- jQuery( '#select404page' ).change(function() {
3
- jQuery( '#edit_404_page, #test_404_page' ).prop( 'disabled', !( jQuery( '#select404page' ).val() == jQuery( '#404page_current_value').text() != 0 ) );
4
- });
5
- jQuery( '#select404page' ).trigger( 'change' );
6
- jQuery( '#edit_404_page' ).click(function() {
7
- window.location.href = jQuery( '#404page_edit_link' ).text();
8
- });
9
- jQuery( '#test_404_page' ).click(function() {
10
- window.location.href = jQuery( '#404page_test_link' ).text();
11
- });
12
- jQuery( '#404page_admin_notice .notice-dismiss' ).click( function() {
13
- jQuery.ajax({
14
- url: ajaxurl,
15
- data: {
16
- action: '404page_dismiss_admin_notice'
17
- }
18
- });
19
- });
20
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404page.php CHANGED
@@ -1,723 +1,74 @@
1
  <?php
2
- /*
3
- Plugin Name: 404page - your smart custom 404 error page
4
- Plugin URI: http://petersplugins.com/free-wordpress-plugins/404page/
5
- Description: Custom 404 the easy way! Set any page as custom 404 error page. No coding needed. Works with (almost) every Theme.
6
- Version: 2.5
7
- Author: Peter Raschendorfer
8
- Author URI: http://petersplugins.com
9
- Text Domain: 404page
10
- License: GPL2+
11
- License URI: http://www.gnu.org/licenses/gpl-2.0.txt
12
- */
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  if ( ! defined( 'WPINC' ) ) {
15
  die;
16
  }
17
 
18
- define( 'PP_404', true );
19
-
20
- class Smart404Page {
21
- public $plugin_name;
22
- public $plugin_slug;
23
- public $version;
24
- private $wp_url;
25
- private $my_url;
26
- private $dc_url;
27
- public $settings;
28
- private $template;
29
- private $postid;
30
-
31
- public function __construct() {
32
- $this->plugin_name = '404page';
33
- $this->plugin_slug = '404page';
34
- $this->version = '2.5';
35
- $this->get_settings();
36
- $this->load();
37
- }
38
-
39
- // get all settings
40
- private function get_settings() {
41
- $this->settings = array();
42
- $this->settings['404page_page_id'] = $this->get_404page_id();
43
- $this->settings['404page_hide'] = $this->get_404page_hide();
44
- $this->settings['404page_fire_error'] = $this->get_404page_fire_error();
45
- // $this->settings['404page_method'] = $this->get_404page_method(); --> moved to set_mode in v 2.2 because this may be too early here
46
- $this->settings['404page_native'] = false;
47
- }
48
-
49
- // load
50
- // this function was introduced in v 2.4 and runs the init() function on firing of init action to ensure everything is loaded properly
51
- private function load() {
52
-
53
- add_action( 'init', array( $this, 'init' ) );
54
-
55
- }
56
-
57
- // do plugin init
58
- // as of v 2.4 this runs after init action has fired to ensure everything is loaded properly
59
- function init() {
60
-
61
- // as of v 2.2 always call set_mode
62
- // as of v 2.4 we do not need to add an init action hook
63
- $this->set_mode();
64
-
65
- if ( !is_admin() ) {
66
-
67
- add_action( 'pre_get_posts', array ( $this, 'exclude_404page' ) );
68
- add_filter( 'get_pages', array ( $this, 'remove_404page_from_array' ), 10, 2 );
69
-
70
- } else {
71
-
72
- add_action( 'admin_init', array( $this, 'admin_init' ) );
73
- add_action( 'admin_menu', array( $this, 'admin_menu' ) );
74
- add_action( 'admin_head', array( $this, 'admin_css' ) );
75
- add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'add_settings_link' ) );
76
-
77
- if ( $this->settings['404page_hide'] and $this->settings['404page_page_id'] > 0 ) {
78
- add_action( 'pre_get_posts' ,array ( $this, 'exclude_404page' ) );
79
- }
80
-
81
- }
82
-
83
- }
84
-
85
- // init filters
86
- function set_mode() {
87
-
88
- $this->settings['404page_method'] = $this->get_404page_method();
89
-
90
- if ( !is_admin() ) {
91
-
92
- if ( defined( 'CUSTOMIZR_VER' ) ) {
93
-
94
- // Customizr Compatibility Mode
95
-
96
- add_filter( 'tc_404_header_content', array( $this, 'show404title_customizr_mode' ), 999 );
97
- add_filter( 'tc_404_content', array( $this, 'show404_customizr_mode' ), 999 );
98
- add_filter( 'tc_404_selectors', array( $this, 'show404articleselectors_customizr_mode' ), 999 );
99
-
100
- } elseif ( $this->settings['404page_method'] != 'STD' ) {
101
-
102
- // Compatibility Mode
103
- // as of v 2.4 we use the the_posts filter instead of posts_results, because the posts array is internally processed after posts_results fires
104
- add_filter( 'the_posts', array( $this, 'show404_compatiblity_mode' ), 999 );
105
-
106
- // as of v 2.5 we remove the filter if the DW Question & Answer plugin by DesignWall (https://www.designwall.com/wordpress/plugins/dw-question-answer/) is active and we're in the answers list
107
- add_filter( 'dwqa_prepare_answers', array( $this, 'remove_show404_compatiblity_mode' ), 999 );
108
-
109
- } else {
110
-
111
- // Standard Mode
112
- add_filter( '404_template', array( $this, 'show404_standard_mode' ), 999 );
113
- if ( $this->settings['404page_fire_error'] ) {
114
- add_action( 'template_redirect', array( $this, 'do_404_header_standard_mode' ) );
115
- }
116
-
117
- }
118
-
119
- }
120
-
121
- }
122
-
123
- // show 404 page - Standard Mode
124
- function show404_standard_mode( $template ) {
125
-
126
- global $wp_query;
127
- $pageid = $this->get_page_id();
128
- if ( $pageid > 0 ) {
129
- if ( ! $this->settings['404page_native'] ) {
130
- $wp_query = null;
131
- $wp_query = new WP_Query();
132
- $wp_query->query( 'page_id=' . $pageid );
133
- $wp_query->the_post();
134
- $template = get_page_template();
135
- rewind_posts();
136
- add_filter( 'body_class', array( $this, 'add_404_body_class' ) );
137
- }
138
- $this->do_404page_action();
139
- }
140
-
141
- return $template;
142
-
143
- }
144
-
145
- // show 404 page - Compatibility Mode
146
- function show404_compatiblity_mode( $posts ) {
147
-
148
- // remove the filter so we handle only the first query - no custom queries
149
- remove_filter( 'the_posts', array( $this, 'show404_compatiblity_mode' ), 999 );
150
-
151
- $pageid = $this->get_page_id();
152
- if ( $pageid > 0 && ! $this->settings['404page_native'] ) {
153
- if ( empty( $posts ) && is_main_query() && !is_robots() && !is_home() && !is_feed() && !is_search() && !is_archive() && ( !defined('DOING_AJAX') || !DOING_AJAX ) ) {
154
-
155
- // as of v2.1 we do not alter the posts argument here because this does not work with SiteOrigin's Page Builder Plugin, template_include filter introduced
156
- $this->postid = $pageid;
157
-
158
- // as of v 2.4 we use the the_posts filter instead of posts_results
159
- // therefore we have to reset $wp_query
160
- // resetting $wp_query also forces us to remove the pre_get_posts action plus the get_pages filter
161
-
162
- remove_action( 'pre_get_posts', array ( $this, 'exclude_404page' ) );
163
- remove_filter( 'get_pages', array ( $this, 'remove_404page_from_array' ), 10, 2 );
164
-
165
- global $wp_query;
166
- $wp_query = null;
167
- $wp_query = new WP_Query();
168
- $wp_query->query( 'page_id=' . $pageid );
169
- $wp_query->the_post();
170
-
171
- $this->template = get_page_template();
172
-
173
- $posts = $wp_query->posts;
174
-
175
- $wp_query->rewind_posts();
176
-
177
 
178
- add_action( 'wp', array( $this, 'do_404_header' ) );
179
- add_filter( 'body_class', array( $this, 'add_404_body_class' ) );
180
- add_filter( 'template_include', array( $this, 'change_404_template' ), 999 );
181
-
182
- $this->do_404page_action();
183
-
184
- } elseif ( 1 == count( $posts ) && 'page' == $posts[0]->post_type ) {
185
-
186
- // Do a 404 if the 404 page is opened directly
187
- if ( $this->settings['404page_fire_error'] ) {
188
- $curpageid = $posts[0]->ID;
189
-
190
- if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
191
-
192
- // WPML is active - get the post ID of the default language
193
- global $sitepress;
194
- $curpageid = apply_filters( 'wpml_object_id', $curpageid, 'page', $sitepress->get_default_language() );
195
- $pageid = apply_filters( 'wpml_object_id', $pageid, 'page', $sitepress->get_default_language() );
196
-
197
- } elseif ( defined( 'POLYLANG_VERSION' ) ) {
198
-
199
- // Polylang is active - get the post ID of the default language
200
- $curpageid = pll_get_post( $curpageid, pll_default_language() );
201
- $pageid = pll_get_post( $pageid, pll_default_language() );
202
-
203
- }
204
-
205
- if ( $pageid == $curpageid ) {
206
- add_action( 'wp', array( $this, 'do_404_header' ) );
207
- add_filter( 'body_class', array( $this, 'add_404_body_class' ) );
208
- $this->do_404page_action();
209
- }
210
- }
211
-
212
- }
213
- } elseif ( $pageid > 0 && $this->settings['404page_native'] ) {
214
- $this->do_404page_action();
215
- }
216
- return $posts;
217
- }
218
-
219
- // this function is called by the dwqa_prepare_answers filter
220
- function remove_show404_compatiblity_mode( $args ) {
221
- remove_filter( 'the_posts', array( $this, 'show404_compatiblity_mode' ), 999 );
222
- return $args;
223
- }
224
-
225
- // this function overrides the page template in compatibilty mode
226
- function change_404_template( $template ) {
227
-
228
- // we have to check if the template file is there because if the theme was changed maybe a wrong template is stored in the database
229
- $new_template = locate_template( array( $this->template ) );
230
- if ( '' != $new_template ) {
231
- return $new_template ;
232
- }
233
- return $template;
234
- }
235
-
236
- // send a 404 HTTP header - Standard Mode
237
- function do_404_header_standard_mode() {
238
- if ( is_page() && get_the_ID() == $this->settings['404page_page_id'] && !is_404() ) {
239
- status_header( 404 );
240
- nocache_headers();
241
- $this->do_404page_action();
242
- }
243
- }
244
-
245
- // send a 404 HTTP header - Compatibility Mode
246
- function do_404_header() {
247
- // remove the action so we handle only the first query - no custom queries
248
- remove_action( 'wp', array( $this, 'do_404_header' ) );
249
- status_header( 404 );
250
- nocache_headers();
251
- }
252
-
253
- // adds the error404 class to the body classes
254
- function add_404_body_class( $classes ) {
255
- $classes[] = 'error404';
256
- return $classes;
257
- }
258
-
259
- // show title - Customizr Compatibility Mode
260
- function show404title_customizr_mode( $title ) {
261
- if ( ! $this->settings['404page_native'] ) {
262
- return '<h1 class="entry-title">' . get_the_title( $this->get_page_id() ) . '</h1>';
263
- } else {
264
- return $title;
265
- }
266
- }
267
-
268
- // show content - Customizr Compatibility Mode
269
- function show404_customizr_mode( $content ) {
270
- if ( ! $this->settings['404page_native'] ) {
271
- return '<div class="entry-content">' . apply_filters( 'the_content', get_post_field( 'post_content', $this->get_page_id() ) ) . '</div>';
272
- } else {
273
- return $content;
274
- }
275
- $this->do_404page_action();
276
- }
277
-
278
- // change article selectors - Customizr Compatibility Mode
279
- function show404articleselectors_customizr_mode( $selectors ) {
280
- if ( ! $this->settings['404page_native'] ) {
281
- return 'id="post-' . $this->get_page_id() . '" ' . 'class="' . join( ' ', get_post_class( 'row-fluid', $this->get_page_id() ) ) . '"';
282
- } else {
283
- return $selectors;
284
- }
285
- }
286
-
287
- // init the admin section
288
- function admin_init() {
289
- $this->wp_url = 'https://wordpress.org/plugins/' . $this->plugin_slug;
290
- $this->my_url = 'http://petersplugins.com/free-wordpress-plugins/' . $this->plugin_slug;
291
- $this->dc_url = 'http://petersplugins.com/docs/' . $this->plugin_slug;
292
- load_plugin_textdomain( '404page' );
293
- add_settings_section( '404page-settings', null, null, '404page_settings_section' );
294
- register_setting( '404page_settings', '404page_page_id' );
295
- register_setting( '404page_settings', '404page_hide' );
296
- register_setting( '404page_settings', '404page_method' );
297
- register_setting( '404page_settings', '404page_fire_error' );
298
- 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' ) );
299
- add_settings_field( '404page_settings_hide', __( 'Hide 404 page', '404page' ) . '&nbsp;<a class="dashicons dashicons-editor-help" href="' . $this->dc_url . '/#settings_hide_page"></a>' , array( $this, 'admin_hide' ), '404page_settings_section', '404page-settings', array( 'label_for' => '404page_hide' ) );
300
- add_settings_field( '404page_settings_fire', __( 'Fire 404 error', '404page' ) . '&nbsp;<a class="dashicons dashicons-editor-help" href="' . $this->dc_url . '/#settings_fire_404"></a>' , array( $this, 'admin_fire404' ), '404page_settings_section', '404page-settings', array( 'label_for' => '404page_fire_error' ) );
301
- add_settings_field( '404page_settings_method', __( 'Operating Method', '404page' ) . '&nbsp;<a class="dashicons dashicons-editor-help" href="' . $this->dc_url . '/#settings_operating_method"></a>' , array( $this, 'admin_method' ), '404page_settings_section', '404page-settings', array( 'label_for' => '404page_method' ) );
302
- }
303
-
304
- // add css
305
- function admin_css() {
306
- echo '<style type="text/css">#select404page {width: 100%; }';
307
- if ( $this->settings['404page_page_id'] > 0 ) {
308
- foreach ( $this->get_all_page_ids() as $pid ) {
309
- echo ' #the-list #post-' . $pid . ' .column-title .row-title:before { content: "404"; background-color: #333; color: #FFF; display: inline-block; padding: 0 5px; margin-right: 10px; }';
310
- }
311
- }
312
- echo '</style>';
313
- }
314
-
315
- // handle the settings field page id
316
- function admin_404page() {
317
- if ( $this->settings['404page_page_id'] < 0 ) {
318
- echo '<div class="error form-invalid" style="line-height: 3em">' . __( 'The page you have selected as 404 page does not exist anymore. Please choose another page.', '404page' ) . '</div>';
319
- }
320
- wp_dropdown_pages( array( 'name' => '404page_page_id', 'id' => 'select404page', 'echo' => 1, 'show_option_none' => __( '&mdash; NONE (WP default 404 page) &mdash;', '404page'), 'option_none_value' => '0', 'selected' => $this->settings['404page_page_id'] ) );
321
- echo '<div id="404page_edit_link" style="display: none">' . get_edit_post_link( $this->get_404page_id() ) . '</div>';
322
- echo '<div id="404page_test_link" style="display: none">' . get_site_url() . '/' . md5( rand() ) . '/' . md5( rand() ) . '/' . md5( rand() ) . '</div>';
323
- echo '<div id="404page_current_value" style="display: none">' . $this->get_404page_id() . '</div>';
324
- echo '<p class="submit"><input type="button" name="edit_404_page" id="edit_404_page" class="button secondary" value="' . __( 'Edit Page', '404page' ) . '" />&nbsp;<input type="button" name="test_404_page" id="test_404_page" class="button secondary" value="' . __( 'Test 404 error', '404page' ) . '" /></p>';
325
- }
326
-
327
- // handle the settings field hide
328
- function admin_hide() {
329
- echo '<p><input type="checkbox" id="404page_hide" name="404page_hide" value="1"' . checked( true, $this->settings['404page_hide'], false ) . '/>';
330
- echo '<label for="404page_hide">' . __( 'Hide the selected page from the Pages list', '404page' ) . '</label></p>';
331
- echo '<p><span class="dashicons dashicons-info"></span>&nbsp;' . __( 'For Administrators the page is always visible.', '404page' ) . '</p>';
332
- }
333
-
334
- // handle the settings field fire 404 error
335
- function admin_fire404() {
336
- echo '<p><input type="checkbox" id="404page_fire_error" name="404page_fire_error" value="1"' . checked( true, $this->settings['404page_fire_error'], false ) . '/>';
337
- echo '<label for="404page_fire_error">' . __( 'Send an 404 error if the page is accessed directly by its URL', '404page' ) . '</label></p>';
338
- echo '<p><span class="dashicons dashicons-info"></span>&nbsp;' . __( 'Uncheck this if you want the selected page to be accessible.', '404page' ) . '</p>';
339
- if ( function_exists( 'wpsupercache_activate' ) ) {
340
- echo '<p><span class="dashicons dashicons-warning"></span>&nbsp;<strong>' . __( 'WP Super Cache Plugin detected', '404page' ) . '</strong>. ' . __ ( 'If the page you selected as 404 error page is in cache, always a HTTP code 200 is sent. To avoid this and send a HTTP code 404 you have to exlcude this page from caching', '404page' ) . ' (<a href="' . admin_url( 'options-general.php?page=wpsupercache&tab=settings#rejecturi' ) . '">' . __( 'Click here', '404page' ) . '</a>).<br />(<a href="' . $this->dc_url . '/#wp_super_cache">' . __( 'Read more', '404page' ) . '</a>)</p>';
341
- }
342
- }
343
-
344
- // handle the settings field method
345
- function admin_method() {
346
 
347
- if ( $this->settings['404page_native'] ) {
348
-
349
- echo '<p><span class="dashicons dashicons-info"></span>&nbsp;' . __( 'This setting is not available because the Theme you are using natively supports the 404page plugin.', '404page' ) . ' (<a href="' . $this->dc_url . '/#native_mode">' . __( 'Read more', '404page' ) . '</a>)</p>';
350
-
351
- } elseif ( defined( 'CUSTOMIZR_VER' ) ) {
352
-
353
- echo '<p><span class="dashicons dashicons-info"></span>&nbsp;' . __( 'This setting is not availbe because the 404page Plugin works in Customizr Compatibility Mode.', '404page' ) . ' (<a href="' . $this->dc_url . '/#special_modes">' . __( 'Read more', '404page' ) . '</a>)</p>';
354
-
355
- } elseif ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
356
-
357
- echo '<p><span class="dashicons dashicons-info"></span>&nbsp;' . __( 'This setting is not availbe because the 404page Plugin works in WPML Mode.', '404page' ) . ' (<a href="' . $this->dc_url . '/#special_modes">' . __( 'Read more', '404page' ) . '</a>)</p>';
358
-
359
- } elseif ( defined( 'xxxPOLYLANG_VERSION' ) ) {
360
-
361
- echo '<p><span class="dashicons dashicons-info"></span>&nbsp;' . __( 'This setting is not availbe because the 404page Plugin works in Polylang Mode.', '404page' ) . ' (<a href="' . $this->dc_url . '/#special_modes">' . __( 'Read more', '404page' ) . '</a>)</p>';
362
-
363
- } else {
364
-
365
- echo '<p><input type="radio" id="404page_settings_method_standard" name="404page_method" value="STD"' . checked( 'STD', $this->settings['404page_method'], false ) . ' />';
366
- echo '<label for="404page_settings_method_standard">' . __( 'Standard Mode', '404page' ) . '</label></p>';
367
-
368
- echo '<p><input type="radio" id="404page_settings_method_compatibility" name="404page_method" value="CMP"' . checked( 'CMP', $this->settings['404page_method'], false ) . '/>';
369
- echo '<label for="404page_settings_method_compatibility">' . __( 'Compatibility Mode', '404page' ) . '</label></p>';
370
-
371
- echo '<p><span class="dashicons dashicons-info"></span>&nbsp;' . __( 'Standard Mode uses the WordPress Template System and should work in most cases. If the 404page plugin does not work properly, probably you are using a theme or plugin that modifies the WordPress Template System. In this case the Compatibility Mode maybe can fix the problem, although it cannot be guaranteed that every possible configuration can be handled by Compatibility Mode. Standard Mode is the recommended method, only switch to Compatibility Mode if you have any problems.', '404page' ) . '</p>';
372
-
373
- }
374
-
375
- }
376
-
377
- // this function hides the selected page from the list of pages
378
- function exclude_404page( $query ) {
379
- $pageid = $this->get_page_id();
380
- if ( $pageid > 0 ) {
381
- global $pagenow;
382
-
383
- $post_type = $query->get( 'post_type' );
384
-
385
- // as of v 2.3 we check the post_type on front end
386
- // as of v 2.5 we also hide the page from search results on front end
387
- if( ( is_admin() && ( 'edit.php' == $pagenow && !current_user_can( 'create_users' ) ) ) || ( ! is_admin() && ( is_search() || ( !empty( $post_type) && ( ('page' === $post_type || 'any' === $post_type) || ( is_array( $post_type ) && in_array( 'page', $post_type ) ) ) ) ) ) ) {
388
-
389
- // as of v 2.4 we hide all translations in admin for WPML
390
- // as of v 2.5 we hide all translations from search results on front end for WPML
391
- if ( is_admin() || ( ! is_admin() && is_search() ) ) {
392
- $pageids = $this->get_all_page_ids();
393
- } else {
394
- $pageids = array( $pageid );
395
- }
396
-
397
- // as of v 2.3 we add the ID of the 404 page to post__not_in
398
- // using just $query->set() overrides existing settings but not adds a new setting
399
- $query->set( 'post__not_in', array_merge( (array)$query->get( 'post__not_in', array() ), $pageids ) );
400
-
401
- }
402
- }
403
- }
404
-
405
- // this function removes the 404 page from get_pages result array
406
- function remove_404page_from_array( $pages, $r ) {
407
- $pageid = $this->get_page_id();
408
- if ( $pageid > 0 ) {
409
- for ( $i = 0; $i < sizeof( $pages ); $i++ ) {
410
- if ( $pages[$i]->ID == $pageid ) {
411
- unset( $pages[$i] );
412
- break;
413
- }
414
- }
415
- }
416
- return array_values( $pages );
417
- }
418
-
419
- // adds the options page to admin menu
420
- function admin_menu() {
421
- $page_handle = add_theme_page ( __( '404 Error Page', "404page" ), __( '404 Error Page', '404page' ), 'manage_options', '404pagesettings', array( $this, 'admin_page' ) );
422
- add_action( 'admin_print_scripts', array( $this, 'admin_js' ) );
423
- }
424
-
425
- // adds javascript to the 404page settings page
426
- function admin_js() {
427
- wp_enqueue_script( '404pagejs', plugins_url( '/404page.js', __FILE__ ), 'jquery', $this->version, true );
428
- }
429
-
430
- // creates the options page
431
- function admin_page() {
432
- if ( !current_user_can( 'manage_options' ) ) {
433
- wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
434
- }
435
- ?>
436
- <div class="wrap">
437
- <?php screen_icon(); ?>
438
- <h2 style="min-height: 32px; line-height: 32px; padding-left: 40px; background-image: url(<?php echo plugins_url( 'pluginicon.png', __FILE__ ); ?>); background-repeat: no-repeat; background-position: left center"><a href="<?php echo $this->my_url; ?>">404page</a> <?php echo __( 'Settings', '404page' ); ?></h2>
439
- <?php settings_errors(); ?>
440
- <hr />
441
- <p>Plugin Version: <?php echo $this->version; ?> <a class="dashicons dashicons-editor-help" href="<?php echo $this->wp_url; ?>/changelog/"></a></p>
442
- <div id="poststuff">
443
- <div id="post-body" class="metabox-holder columns-2">
444
- <div id="post-body-content">
445
- <div class="meta-box-sortables ui-sortable">
446
- <form method="post" action="options.php">
447
- <div class="postbox">
448
- <div class="inside">
449
- <?php
450
- settings_fields( '404page_settings' );
451
- do_settings_sections( '404page_settings_section' );
452
- submit_button();
453
- ?>
454
- </div>
455
- </div>
456
- </form>
457
- </div>
458
- </div>
459
- <?php { $this->show_meta_boxes(); } ?>
460
- </div>
461
- <br class="clear">
462
- </div>
463
- </div>
464
- <?php
465
- }
466
-
467
- // returns the id of the 404 page if one is defined, returns 0 if none is defined, returns -1 if the defined page id does not exist
468
- private function get_404page_id() {
469
- $pageid = get_option( '404page_page_id', 0 );
470
- if ( $pageid != 0 ) {
471
- $page = get_post( $pageid );
472
- if ( !$page || $page->post_status != 'publish' ) {
473
- $pageid = -1;
474
- }
475
- }
476
- return $pageid;
477
- }
478
-
479
- // returns the selected method
480
- private function get_404page_method() {
481
- if ( defined( 'ICL_SITEPRESS_VERSION' ) || defined( 'xxxPOLYLANG_VERSION' ) ) {
482
- // WPML or Polylang is active
483
- return 'CMP';
484
- } else {
485
- return get_option( '404page_method', 'STD' );
486
- }
487
- }
488
-
489
- // should we hide the selected 404 page from the page list?
490
- private function get_404page_hide() {
491
- return (bool)get_option( '404page_hide', false );
492
- }
493
-
494
- // should we fire an 404 error if the selected page is accessed directly?
495
- private function get_404page_fire_error() {
496
- return (bool)get_option( '404page_fire_error', true );
497
- }
498
-
499
- // as of version 2.4 this function returns the page id of the 404 page in the current language
500
- // in previous versions this functions required a parameter and only did the translation if WPML or Polylang is active
501
- // now we have all in one function
502
- private function get_page_id() {
503
-
504
- $pageid = $this->settings['404page_page_id'];
505
-
506
- if ( $pageid > 0 ) {
507
-
508
- if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
509
-
510
- // WPML is active
511
- $pageid = apply_filters( 'wpml_object_id', $pageid, 'page', true );
512
-
513
- } elseif ( defined( 'POLYLANG_VERSION' ) ) {
514
-
515
- // Polylang is active
516
- $translatedpageid = pll_get_post( $pageid );
517
- if ( !empty( $translatedpageid ) && 'publish' == get_post_status( $translatedpageid ) ) {
518
- $pageid = $translatedpageid;
519
- }
520
- }
521
-
522
- }
523
-
524
- return $pageid;
525
-
526
- }
527
-
528
- // if WPML is active this function returns an array of all page ids in all available languages
529
- // otherwise it returns the page id as array
530
- // introduced in v 2.4
531
- private function get_all_page_ids() {
532
-
533
- if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
534
-
535
- // WPML is active
536
- // get an array for all translations
537
-
538
- $pageid = $this->settings['404page_page_id'];
539
- $pages = array( $pageid );
540
- if ( $pageid > 0 ) {
541
- $languages = apply_filters( 'wpml_active_languages', NULL );
542
- if ( !empty( $languages ) ) {
543
- foreach( $languages as $l ) {
544
- $p = apply_filters( 'wpml_object_id', $pageid, 'page', false, $l['language_code'] );
545
- if ( $p ) {
546
- $pages[] = $p;
547
- }
548
- }
549
- }
550
- }
551
- $pageids = array_unique( $pages, SORT_NUMERIC );
552
-
553
- } else {
554
-
555
- $pageids = array( $this->get_page_id() );
556
-
557
- }
558
-
559
- return $pageids;
560
-
561
- }
562
-
563
- // make plugin expandable
564
- function do_404page_action() {
565
- do_action( '404page_after_404' );
566
- }
567
-
568
- // show meta boxes
569
- function show_meta_boxes() {
570
- ?>
571
- <div id="postbox-container-1" class="postbox-container">
572
- <div class="meta-box-sortables">
573
- <div class="postbox">
574
- <h3><span><?php _e( 'Like this Plugin?', '404page' ); ?></span></h3>
575
- <div class="inside">
576
- <ul>
577
- <li><div class="dashicons dashicons-wordpress"></div>&nbsp;&nbsp;<a href="<?php echo $this->wp_url; ?>/"><?php _e( 'Please rate the plugin', '404page' ); ?></a></li>
578
- <li><div class="dashicons dashicons-admin-home"></div>&nbsp;&nbsp;<a href="<?php echo $this->my_url; ?>/"><?php _e( 'Plugin homepage', '404page'); ?></a></li>
579
- <li><div class="dashicons dashicons-admin-home"></div>&nbsp;&nbsp;<a href="http://petersplugins.com/"><?php _e( 'Author homepage', '404page' );?></a></li>
580
- <li><div class="dashicons dashicons-googleplus"></div>&nbsp;&nbsp;<a href="http://g.petersplugins.com/"><?php _e( 'Authors Google+ Page', '404page' ); ?></a></li>
581
- <li><div class="dashicons dashicons-facebook-alt"></div>&nbsp;&nbsp;<a href="http://f.petersplugins.com/"><?php _e( 'Authors facebook Page', '404page' ); ?></a></li>
582
- </ul>
583
- </div>
584
- </div>
585
- <div class="postbox">
586
- <h3><span><?php _e( 'Need help?', '404page' ); ?></span></h3>
587
- <div class="inside">
588
- <ul>
589
- <li><div class="dashicons dashicons-book-alt"></div>&nbsp;&nbsp;<a href="<?php echo $this->dc_url; ?>"><?php _e( 'Take a look at the Plugin Doc', '404page' ); ?></a></li>
590
- <li><div class="dashicons dashicons-wordpress"></div>&nbsp;&nbsp;<a href="<?php echo $this->wp_url; ?>/faq/"><?php _e( 'Take a look at the FAQ section', '404page' ); ?></a></li>
591
- <li><div class="dashicons dashicons-wordpress"></div>&nbsp;&nbsp;<a href="http://wordpress.org/support/plugin/<?php echo $this->plugin_slug; ?>/"><?php _e( 'Take a look at the Support section', '404page'); ?></a></li>
592
- <li><div class="dashicons dashicons-admin-comments"></div>&nbsp;&nbsp;<a href="http://petersplugins.com/contact/"><?php _e( 'Feel free to contact the Author', '404page' ); ?></a></li>
593
- </ul>
594
- </div>
595
- </div>
596
- <div class="postbox">
597
- <h3><span><?php _e( 'Translate this Plugin', '404page' ); ?></span></h3>
598
- <div class="inside">
599
- <p><?php _e( 'It would be great if you\'d support the 404page Plugin by adding a new translation or keeping an existing one up to date!', '404page' ); ?></p>
600
- <p><a href="https://translate.wordpress.org/projects/wp-plugins/<?php echo $this->plugin_slug; ?>"><?php _e( 'Translate online', '404page' ); ?></a></p>
601
- </div>
602
- </div>
603
- </div>
604
- </div>
605
- <?php
606
- }
607
-
608
- // add a link to settings page in plugin list
609
- function add_settings_link( $links ) {
610
- return array_merge( $links, array( '<a href="' . admin_url( 'themes.php?page=404pagesettings' ) . '">' . __( 'Settings', '404page' ) . '</a>') );
611
- }
612
-
613
- // uninstall plugin
614
- function uninstall() {
615
- if( is_multisite() ) {
616
- $this->uninstall_network();
617
- } else {
618
- $this->uninstall_single();
619
- }
620
- }
621
-
622
- // uninstall network wide
623
- function uninstall_network() {
624
- global $wpdb;
625
- $activeblog = $wpdb->blogid;
626
- $blogids = $wpdb->get_col( esc_sql( 'SELECT blog_id FROM ' . $wpdb->blogs ) );
627
- foreach ($blogids as $blogid) {
628
- switch_to_blog( $blogid );
629
- $this->uninstall_single();
630
- }
631
- switch_to_blog( $activeblog );
632
- }
633
-
634
- // uninstall single blog
635
- function uninstall_single() {
636
- foreach ( $this->settings as $key => $value) {
637
- delete_option( $key );
638
- }
639
- }
640
-
641
- // *
642
- // * functions for theme usage
643
- // *
644
-
645
- // check if there's a custom 404 page set
646
- function pp_404_is_active() {
647
- return ( $this->settings['404page_page_id'] > 0 );
648
- }
649
-
650
- // activate the native theme support
651
- function pp_404_set_native_support() {
652
- $this->settings['404page_native'] = true;
653
- }
654
-
655
- // get the title - native theme support
656
- function pp_404_get_the_title() {
657
- $title = '';
658
- if ( $this->settings['404page_page_id'] > 0 && $this->settings['404page_native'] ) {
659
- $title = get_the_title( $this->get_page_id() );
660
- }
661
- return $title;
662
- }
663
-
664
- // print title - native theme support
665
- function pp_404_the_title() {
666
- echo $this->pp_404_get_the_title();
667
- }
668
-
669
- // get the content - native theme support
670
- function pp_404_get_the_content() {
671
- $content = '';
672
- if ( $this->settings['404page_page_id'] > 0 && $this->settings['404page_native'] ) {
673
- $content = apply_filters( 'the_content', get_post_field( 'post_content', $this->get_page_id() ) );
674
- }
675
- return $content;
676
- }
677
-
678
- // print content - native theme support
679
- function pp_404_the_content() {
680
- echo $this->pp_404_get_the_content();
681
- }
682
-
683
- }
684
 
685
- $smart404page = new Smart404Page();
 
 
686
 
687
  // this function can be used by a theme to check if there's an active custom 404 page
688
  function pp_404_is_active() {
689
- global $smart404page;
690
- return $smart404page->pp_404_is_active();
691
  }
692
 
693
  // this function can be used by a theme to activate native support
694
  function pp_404_set_native_support() {
695
- global $smart404page;
696
- $smart404page->pp_404_set_native_support();
697
  }
698
 
699
  // this function can be used by a theme to get the title of the custom 404 page in native support
700
  function pp_404_get_the_title() {
701
- global $smart404page;
702
- return $smart404page->pp_404_get_the_title();
703
  }
704
 
705
  // this function can be used by a theme to print out the title of the custom 404 page in native support
706
  function pp_404_the_title() {
707
- global $smart404page;
708
- $smart404page->pp_404_the_title();
709
  }
710
 
711
  // this function can be used by a theme to get the content of the custom 404 page in native support
712
  function pp_404_get_the_content() {
713
- global $smart404page;
714
- return $smart404page->pp_404_get_the_content();
715
  }
716
 
717
  // this function can be used by a theme to print out the content of the custom 404 page in native support
718
  function pp_404_the_content() {
719
- global $smart404page;
720
- return $smart404page->pp_404_the_content();
721
  }
722
 
723
  ?>
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
2
 
3
+ /**
4
+ * The 404page Plugin
5
+ *
6
+ * 404page allows creation of 404 error pages in WordPress admin
7
+ *
8
+ * @wordpress-plugin
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.0
13
+ * Author: Peter Raschendorfer
14
+ * Author URI: http://petersplugins.com
15
+ * Text Domain: 404page
16
+ * License: GPL2+
17
+ * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
18
+ */
19
+
20
+
21
+ // If this file is called directly, abort
22
  if ( ! defined( 'WPINC' ) ) {
23
  die;
24
  }
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
+ /**
28
+ * Load core plugin class and run the plugin
29
+ */
30
+ require_once( plugin_dir_path( __FILE__ ) . '/inc/class-404page.php' );
31
+ $pp_404page = new PP_404Page( __FILE__ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
+ /**
35
+ * Theme functions
36
+ */
37
 
38
  // this function can be used by a theme to check if there's an active custom 404 page
39
  function pp_404_is_active() {
40
+ global $pp_404page;
41
+ return $pp_404page->pp_404_is_active();
42
  }
43
 
44
  // this function can be used by a theme to activate native support
45
  function pp_404_set_native_support() {
46
+ global $pp_404page;
47
+ $pp_404page->pp_404_set_native_support();
48
  }
49
 
50
  // this function can be used by a theme to get the title of the custom 404 page in native support
51
  function pp_404_get_the_title() {
52
+ global $pp_404page;
53
+ return $pp_404page->pp_404_get_the_title();
54
  }
55
 
56
  // this function can be used by a theme to print out the title of the custom 404 page in native support
57
  function pp_404_the_title() {
58
+ global $pp_404page;
59
+ $pp_404page->pp_404_the_title();
60
  }
61
 
62
  // this function can be used by a theme to get the content of the custom 404 page in native support
63
  function pp_404_get_the_content() {
64
+ global $pp_404page;
65
+ return $pp_404page->pp_404_get_the_content();
66
  }
67
 
68
  // this function can be used by a theme to print out the content of the custom 404 page in native support
69
  function pp_404_the_content() {
70
+ global $pp_404page;
71
+ return $pp_404page->pp_404_the_content();
72
  }
73
 
74
  ?>
assets/css/404page-ui.css ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pp-404page-settings .form-table th, .form-table td {
2
+ display: block;
3
+ width: auto;
4
+ }
5
+
6
+ #pp-404page-settings .form-table th {
7
+ padding: 20px 10px 0 0;
8
+ }
9
+
10
+ #pp-404page-settings .form-table td {
11
+ padding: 6px 10px 0 0;
12
+ }
13
+
14
+ #pp-seetings-advanced .form-table th {
15
+ display: none;
16
+ }
17
+
18
+ #pp-seetings-advanced .form-table td p:first-child {
19
+ font-weight: 600;
20
+ }
21
+
22
+ #pp-seetings-advanced .form-table td p:last-child {
23
+ padding: 0 0 20px 40px;
24
+ }
25
+
26
+ .ui-accordion .ui-accordion-header {
27
+ cursor: pointer;
28
+ outline: 0;
29
+ }
30
+ .ui-accordion .ui-accordion-header:before {
31
+ font-family: dashicons;
32
+ content: "\f132";
33
+ margin-right: 10px;
34
+ float: left;
35
+ }
36
+
37
+ .ui-accordion .ui-accordion-header-active:before {
38
+ content: "\f460";
39
+ }
40
+
41
+ .ui-accordion-content {
42
+ padding-left: 30px;
43
+ }
44
+
45
+ #pp-404page-settings input[type="checkbox"] {
46
+ display: none;
47
+ }
48
+
49
+ #pp-404page-settings input[type="checkbox"] + label.check {
50
+ display: inline-block;
51
+ border: 2px solid #DDD;
52
+ box-shadow: 0px 0px 5px 0px rgba(42,42,42,.75);
53
+ border-style:solid;
54
+ border-radius:5px;
55
+ width: 30px;
56
+ height: 30px;
57
+ line-height: 30px;
58
+ text-align: center;
59
+ font-family: dashicons;
60
+ font-size: 2em;
61
+ margin-right: 10px;
62
+ }
63
+
64
+ #pp-404page-settings input[type="checkbox"]:disabled + label.check {
65
+ background-color: #DDD;
66
+ cursor: not-allowed;
67
+ }
68
+
69
+ #pp-404page-settings input[type="checkbox"] + label.check:before {
70
+ content: "";
71
+ }
72
+
73
+ #pp-404page-settings input[type="checkbox"]:enabled:checked + label.check:before {
74
+ content: "\f147";
75
+ }
76
+
77
+
78
+
79
+ #pp-seetings-advanced>div {
80
+ display: none;
81
+ }
82
+
83
+ #pp-404page-settings select {
84
+ border: 2px solid #DDD;
85
+ box-shadow: 0px 0px 5px 0px rgba(42,42,42,.75);
86
+ border-style:solid;
87
+ border-radius:5px;
88
+ height: 40px;
89
+ line-height: 40px;
90
+ }
91
+
92
+ #pp-404page-settings .dashicons-warning, #pp-404page-settings input[type="checkbox"] + label.check.warning:before {
93
+ color: #d54e21;
94
+ }
assets/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden
assets/js/404page-ui.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($) {
2
+ $( '#select404page' ).change(function() {
3
+ $( '#edit_404_page, #test_404_page' ).prop( 'disabled', !( $( '#select404page' ).val() == $( '#404page_current_value').text() != 0 ) );
4
+ });
5
+ $( '#select404page' ).trigger( 'change' );
6
+ $( '#edit_404_page' ).click(function() {
7
+ window.location.href = $( '#404page_edit_link' ).text();
8
+ });
9
+ $( '#test_404_page' ).click(function() {
10
+ window.location.href = $( '#404page_test_link' ).text();
11
+ });
12
+ $( '#pp-404page-settings-advanced' ).accordion({ collapsible: true, active: false });
13
+ });
assets/js/404page.js ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($) {
2
+ $( '#pp-404page-admin-notice-1' ).on( 'click', '.notice-dismiss', function ( event ) {
3
+ event.preventDefault();
4
+ data = {
5
+ action: 'pp_404page_dismiss_admin_notice',
6
+ pp_404page_dismiss_admin_notice: pp_404page_remove.pp_404page_dismiss_admin_notice_number
7
+ };
8
+ $.post( ajaxurl, data );
9
+ return false;
10
+ });
11
+ });
assets/js/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden
assets/pluginicon.png ADDED
Binary file
inc/class-404page.php ADDED
@@ -0,0 +1,1053 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The 404page core plugin class
5
+ */
6
+
7
+
8
+ // If this file is called directly, abort
9
+ if ( ! defined( 'WPINC' ) ) {
10
+ die;
11
+ }
12
+
13
+
14
+ // indicate that 404page plugin is active
15
+ if ( ! defined( 'PP_404' ) ) {
16
+ define( 'PP_404', true );
17
+ }
18
+
19
+
20
+ /**
21
+ * The core plugin class
22
+ */
23
+ if ( !class_exists( 'PP_404Page' ) ) {
24
+
25
+
26
+ class PP_404Page {
27
+ public $plugin_name;
28
+ public $plugin_slug;
29
+ public $version;
30
+ private $_file;
31
+ private $wp_url;
32
+ private $my_url;
33
+ private $dc_url;
34
+ private $settings;
35
+ private $template;
36
+ private $postid;
37
+ private $admin_handle;
38
+
39
+
40
+ /**
41
+ * here we go
42
+ */
43
+ public function __construct( $file ) {
44
+ $this->_file = $file;
45
+ $this->plugin_name = '404page';
46
+ $this->plugin_slug = '404page';
47
+ $this->version = '3.0';
48
+ $this->get_settings();
49
+ $this->load();
50
+ }
51
+
52
+
53
+ /**
54
+ * get all settings
55
+ * except 404page_method
56
+ * the 404page_method setting is set in function set_mode() because it may be too early here and not everything is loaded properly
57
+ */
58
+ private function get_settings() {
59
+ $this->settings = array();
60
+ $this->settings['404page_page_id'] = $this->get_404page_id();
61
+ $this->settings['404page_hide'] = $this->get_404page_hide();
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
+
68
+
69
+ /**
70
+ * Load
71
+ * runs the init() function on firing of init action to ensure everything is loaded properly
72
+ */
73
+ private function load() {
74
+
75
+ $this->wp_url = 'https://wordpress.org/plugins/' . $this->plugin_slug;
76
+ $this->my_url = 'http://petersplugins.com/free-wordpress-plugins/' . $this->plugin_slug;
77
+ $this->dc_url = 'http://petersplugins.com/docs/' . $this->plugin_slug;
78
+
79
+ add_action( 'init', array( $this, 'add_text_domain' ) );
80
+ add_action( 'init', array( $this, 'init' ) );
81
+
82
+ add_action( 'admin_notices', array( $this, 'admin_notices' ) );
83
+ add_action( 'wp_ajax_pp_404page_dismiss_admin_notice', array( $this, 'dismiss_admin_notice' ) );
84
+
85
+ }
86
+
87
+
88
+ /**
89
+ * do plugin init
90
+ * this runs after init action has fired to ensure everything is loaded properly
91
+ */
92
+ function init() {
93
+
94
+ // as of v 2.2 always call set_mode
95
+ // as of v 2.4 we do not need to add an init action hook
96
+
97
+ if ( !is_admin() && $this->settings['404page_page_id'] > 0 ) {
98
+
99
+ // as of v 3.0 we once check if there's a 404 page set and not in all functions separately
100
+ $this->set_mode();
101
+ add_action( 'pre_get_posts', array ( $this, 'exclude_404page' ) );
102
+ add_filter( 'get_pages', array ( $this, 'remove_404page_from_array' ), 10, 2 );
103
+
104
+ // Stop URL guessing if activated
105
+ if ( $this->settings['404page_no_url_guessing'] ) {
106
+ add_filter( 'redirect_canonical' ,array ( $this, 'no_url_guessing' ) );
107
+ }
108
+
109
+ } else {
110
+
111
+ add_action( 'admin_init', array( $this, 'admin_init' ) );
112
+ add_action( 'admin_menu', array( $this, 'admin_menu' ) );
113
+ add_action( 'admin_head', array( $this, 'admin_style' ) );
114
+ add_filter( 'plugin_action_links_' . plugin_basename( $this->_file ), array( $this, 'add_settings_links' ) );
115
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_js' ) );
116
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_css' ) );
117
+
118
+ // Remove 404 page from post list if activated
119
+ if ( $this->settings['404page_hide'] and $this->settings['404page_page_id'] > 0 ) {
120
+ add_action( 'pre_get_posts' ,array ( $this, 'exclude_404page' ) );
121
+ }
122
+
123
+ }
124
+
125
+ }
126
+
127
+
128
+ /**
129
+ * add text domain
130
+ */
131
+ function add_text_domain() {
132
+
133
+ load_plugin_textdomain( '404page' );
134
+
135
+ }
136
+
137
+
138
+ /**
139
+ * init filters
140
+ */
141
+ function set_mode() {
142
+
143
+ $this->settings['404page_method'] = $this->get_404page_method();
144
+
145
+ if ( defined( 'CUSTOMIZR_VER' ) ) {
146
+
147
+ // Customizr Compatibility Mode
148
+
149
+ add_filter( 'tc_404_header_content', array( $this, 'show404title_customizr_mode' ), 999 );
150
+ add_filter( 'tc_404_content', array( $this, 'show404_customizr_mode' ), 999 );
151
+ add_filter( 'tc_404_selectors', array( $this, 'show404articleselectors_customizr_mode' ), 999 );
152
+
153
+ } elseif ( $this->settings['404page_method'] != 'STD' ) {
154
+
155
+ // Compatibility Mode
156
+ // as of v 2.4 we use the the_posts filter instead of posts_results, because the posts array is internally processed after posts_results fires
157
+ add_filter( 'the_posts', array( $this, 'show404_compatiblity_mode' ), 999 );
158
+
159
+ // as of v 2.5 we remove the filter if the DW Question & Answer plugin by DesignWall (https://www.designwall.com/wordpress/plugins/dw-question-answer/) is active and we're in the answers list
160
+ add_filter( 'dwqa_prepare_answers', array( $this, 'remove_show404_compatiblity_mode' ), 999 );
161
+
162
+ } else {
163
+
164
+ // Standard Mode
165
+ add_filter( '404_template', array( $this, 'show404_standard_mode' ), 999 );
166
+ if ( $this->settings['404page_fire_error'] ) {
167
+ add_action( 'template_redirect', array( $this, 'do_404_header_standard_mode' ) );
168
+ }
169
+
170
+ }
171
+
172
+ }
173
+
174
+
175
+ /**
176
+ * show 404 page
177
+ * Standard Mode
178
+ */
179
+ function show404_standard_mode( $template ) {
180
+
181
+ global $wp_query;
182
+ if ( ! $this->settings['404page_native'] ) {
183
+ $wp_query = null;
184
+ $wp_query = new WP_Query();
185
+ $wp_query->query( 'page_id=' . $this->get_page_id() );
186
+ $wp_query->the_post();
187
+ $template = get_page_template();
188
+ rewind_posts();
189
+ add_filter( 'body_class', array( $this, 'add_404_body_class' ) );
190
+ }
191
+ $this->maybe_force_404();
192
+ $this->do_404page_action();
193
+ return $template;
194
+
195
+ }
196
+
197
+ /**
198
+ * show 404 page
199
+ * Compatibility Mode
200
+ */
201
+ function show404_compatiblity_mode( $posts ) {
202
+
203
+ // remove the filter so we handle only the first query - no custom queries
204
+ remove_filter( 'the_posts', array( $this, 'show404_compatiblity_mode' ), 999 );
205
+
206
+ $pageid = $this->get_page_id();
207
+ if ( ! $this->settings['404page_native'] ) {
208
+ if ( empty( $posts ) && is_main_query() && !is_robots() && !is_home() && !is_feed() && !is_search() && !is_archive() && ( !defined('DOING_AJAX') || !DOING_AJAX ) ) {
209
+
210
+ // as of v2.1 we do not alter the posts argument here because this does not work with SiteOrigin's Page Builder Plugin, template_include filter introduced
211
+ $this->postid = $pageid;
212
+
213
+ // as of v 2.4 we use the the_posts filter instead of posts_results
214
+ // therefore we have to reset $wp_query
215
+ // resetting $wp_query also forces us to remove the pre_get_posts action plus the get_pages filter
216
+
217
+ remove_action( 'pre_get_posts', array ( $this, 'exclude_404page' ) );
218
+ remove_filter( 'get_pages', array ( $this, 'remove_404page_from_array' ), 10, 2 );
219
+
220
+ global $wp_query;
221
+ $wp_query = null;
222
+ $wp_query = new WP_Query();
223
+ $wp_query->query( 'page_id=' . $pageid );
224
+ $wp_query->the_post();
225
+
226
+ $this->template = get_page_template();
227
+ $posts = $wp_query->posts;
228
+ $wp_query->rewind_posts();
229
+
230
+ add_action( 'wp', array( $this, 'do_404_header' ) );
231
+ add_filter( 'body_class', array( $this, 'add_404_body_class' ) );
232
+ add_filter( 'template_include', array( $this, 'change_404_template' ), 999 );
233
+
234
+ $this->maybe_force_404();
235
+ $this->do_404page_action();
236
+
237
+ } elseif ( 1 == count( $posts ) && 'page' == $posts[0]->post_type ) {
238
+
239
+ // Do a 404 if the 404 page is opened directly
240
+ if ( $this->settings['404page_fire_error'] ) {
241
+ $curpageid = $posts[0]->ID;
242
+
243
+ if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
244
+
245
+ // WPML is active - get the post ID of the default language
246
+ global $sitepress;
247
+ $curpageid = apply_filters( 'wpml_object_id', $curpageid, 'page', $sitepress->get_default_language() );
248
+ $pageid = apply_filters( 'wpml_object_id', $pageid, 'page', $sitepress->get_default_language() );
249
+
250
+ }
251
+
252
+ if ( $pageid == $curpageid ) {
253
+ add_action( 'wp', array( $this, 'do_404_header' ) );
254
+ add_filter( 'body_class', array( $this, 'add_404_body_class' ) );
255
+ $this->maybe_force_404();
256
+ $this->do_404page_action();
257
+ }
258
+ }
259
+
260
+ }
261
+ } else {
262
+ $this->maybe_force_404();
263
+ $this->do_404page_action();
264
+ }
265
+ return $posts;
266
+ }
267
+
268
+
269
+ /**
270
+ * for DW Question & Answer plugin
271
+ * this function is called by the dwqa_prepare_answers filter
272
+ */
273
+ function remove_show404_compatiblity_mode( $args ) {
274
+ remove_filter( 'the_posts', array( $this, 'show404_compatiblity_mode' ), 999 );
275
+ return $args;
276
+ }
277
+
278
+
279
+ /**
280
+ * this function overrides the page template in compatibilty mode
281
+ */
282
+ function change_404_template( $template ) {
283
+
284
+ // we have to check if the template file is there because if the theme was changed maybe a wrong template is stored in the database
285
+ $new_template = locate_template( array( $this->template ) );
286
+ if ( '' != $new_template ) {
287
+ return $new_template ;
288
+ }
289
+ return $template;
290
+ }
291
+
292
+
293
+ /**
294
+ * send 404 HTTP header
295
+ * Standard Mode
296
+ */
297
+ function do_404_header_standard_mode() {
298
+ if ( is_page() && get_the_ID() == $this->settings['404page_page_id'] && !is_404() ) {
299
+ status_header( 404 );
300
+ nocache_headers();
301
+ $this->maybe_force_404();
302
+ $this->do_404page_action();
303
+ }
304
+ }
305
+
306
+
307
+ /**
308
+ * send 404 HTTP header
309
+ * Compatibility Mode
310
+ */
311
+ function do_404_header() {
312
+ // remove the action so we handle only the first query - no custom queries
313
+ remove_action( 'wp', array( $this, 'do_404_header' ) );
314
+ status_header( 404 );
315
+ nocache_headers();
316
+ }
317
+
318
+
319
+ /**
320
+ * add class error404 to the body classes
321
+ */
322
+ function add_404_body_class( $classes ) {
323
+ $classes[] = 'error404';
324
+ return $classes;
325
+ }
326
+
327
+
328
+ /**
329
+ * show title
330
+ * Customizr Compatibility Mode
331
+ */
332
+ function show404title_customizr_mode( $title ) {
333
+ if ( ! $this->settings['404page_native'] ) {
334
+ return '<h1 class="entry-title">' . get_the_title( $this->get_page_id() ) . '</h1>';
335
+ } else {
336
+ return $title;
337
+ }
338
+ }
339
+
340
+
341
+ /**
342
+ * show content
343
+ * Customizr Compatibility Mode
344
+ */
345
+ function show404_customizr_mode( $content ) {
346
+ if ( ! $this->settings['404page_native'] ) {
347
+ return '<div class="entry-content">' . apply_filters( 'the_content', get_post_field( 'post_content', $this->get_page_id() ) ) . '</div>';
348
+ } else {
349
+ return $content;
350
+ }
351
+ $this->do_404page_action();
352
+ }
353
+
354
+
355
+ /**
356
+ * change article selectors
357
+ * Customizr Compatibility Mode
358
+ */
359
+ function show404articleselectors_customizr_mode( $selectors ) {
360
+ if ( ! $this->settings['404page_native'] ) {
361
+ return 'id="post-' . $this->get_page_id() . '" ' . 'class="' . join( ' ', get_post_class( 'row-fluid', $this->get_page_id() ) ) . '"';
362
+ } else {
363
+ return $selectors;
364
+ }
365
+ }
366
+
367
+
368
+ /**
369
+ * do we have to force a 404 in wp_head?
370
+ */
371
+ function maybe_force_404() {
372
+ if ( $this->settings['404page_force_error'] ) {
373
+ add_action( 'wp_head', array( $this, 'force_404_start' ), 9.9 );
374
+ add_action( 'wp_head', array( $this, 'force_404_end' ), 99 );
375
+ }
376
+ }
377
+
378
+
379
+ /**
380
+ * Force 404 in wp_head start
381
+ * potentially dangerous!
382
+ */
383
+ function force_404_start() {
384
+ global $wp_query;
385
+ $wp_query->is_404 = true;
386
+ }
387
+
388
+
389
+ /**
390
+ * Force 404 in wp_head end
391
+ * potentially dangerous!
392
+ */
393
+ function force_404_end() {
394
+ global $wp_query;
395
+ $wp_query->is_404 = false;
396
+ }
397
+
398
+
399
+ /**
400
+ * disable URL autocorrect guessing
401
+ */
402
+ function no_url_guessing( $redirect_url ) {
403
+ if ( is_404() && !isset($_GET['p']) ) {
404
+ $redirect_url = false;
405
+ }
406
+ return $redirect_url;
407
+ }
408
+
409
+
410
+ /**
411
+ * init admin
412
+ */
413
+ function admin_init() {
414
+
415
+ $this->settings['404page_method'] = $this->get_404page_method();
416
+
417
+
418
+ add_settings_section( '404page-settings', null, null, '404page_settings_section' );
419
+ add_settings_section( '404page-settings', null, null, '404page_settings_section_advanced' );
420
+ register_setting( '404page_settings', '404page_page_id' );
421
+ register_setting( '404page_settings', '404page_hide' );
422
+ register_setting( '404page_settings', '404page_method', array( $this, 'handle_method' ) );
423
+ register_setting( '404page_settings', '404page_fire_error' );
424
+ register_setting( '404page_settings', '404page_force_error' );
425
+ register_setting( '404page_settings', '404page_no_url_guessing' );
426
+ 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' ) );
427
+ add_settings_field( '404page_settings_hide', '' , array( $this, 'admin_hide' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_hide' ) );
428
+ add_settings_field( '404page_settings_fire', '' , array( $this, 'admin_fire404' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_fire_error' ) );
429
+ add_settings_field( '404page_settings_force', '' , array( $this, 'admin_force404' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_force_error' ) );
430
+ add_settings_field( '404page_settings_noguess', '' , array( $this, 'admin_noguess' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_no_url_guessing' ) );
431
+ add_settings_field( '404page_settings_method', '', array( $this, 'admin_method' ), '404page_settings_section_advanced', '404page-settings', array( 'label_for' => '404page_method' ) );
432
+ }
433
+
434
+
435
+ /**
436
+ * add admin css to header
437
+ */
438
+ function admin_style() {
439
+
440
+ echo '<style type="text/css">#pp-plugin-info-404page{ min-height: 48px; line-height: 48px; vertical-align: middle; padding-left: 60px; background-image: url(' . plugins_url( 'assets/pluginicon.png', $this->_file ) .'); background-repeat: no-repeat; background-position: left center;}#pp-plugin-info-404page span{float: right; padding-left: 50px;}#pp-plugin-info-404page .dashicons{ vertical-align: middle; }#select404page {width: 100%; }';
441
+
442
+ if ( $this->settings['404page_page_id'] > 0 ) {
443
+
444
+ foreach ( $this->get_all_page_ids() as $pid ) {
445
+
446
+ echo ' #the-list #post-' . $pid . ' .column-title .row-title:before { content: "404"; background-color: #333; color: #FFF; display: inline-block; padding: 0 5px; margin-right: 10px; }';
447
+
448
+ }
449
+
450
+ }
451
+
452
+ echo '</style>';
453
+
454
+ }
455
+
456
+
457
+ /**
458
+ * handle the settings field page id
459
+ */
460
+ function admin_404page() {
461
+
462
+ if ( $this->settings['404page_page_id'] < 0 ) {
463
+
464
+ echo '<div class="error form-invalid" style="line-height: 3em">' . __( 'The page you have selected as 404 page does not exist anymore. Please choose another page.', '404page' ) . '</div>';
465
+ }
466
+
467
+ wp_dropdown_pages( array( 'name' => '404page_page_id', 'id' => 'select404page', 'echo' => 1, 'show_option_none' => __( '&mdash; NONE (WP default 404 page) &mdash;', '404page'), 'option_none_value' => '0', 'selected' => $this->settings['404page_page_id'] ) );
468
+
469
+ echo '<div id="404page_edit_link" style="display: none">' . get_edit_post_link( $this->settings['404page_page_id'] ) . '</div>';
470
+ echo '<div id="404page_test_link" style="display: none">' . get_site_url() . '/404page-test-' . md5( rand() ) . '</div>';
471
+ echo '<div id="404page_current_value" style="display: none">' . $this->settings['404page_page_id'] . '</div>';
472
+ echo '<p class="submit"><input type="button" name="edit_404_page" id="edit_404_page" class="button secondary" value="' . __( 'Edit Page', '404page' ) . '" />&nbsp;<input type="button" name="test_404_page" id="test_404_page" class="button secondary" value="' . __( 'Test 404 error', '404page' ) . '" /></p>';
473
+
474
+ }
475
+
476
+
477
+ /**
478
+ * handle the settings field hide
479
+ */
480
+ function admin_hide() {
481
+
482
+ echo '<p><input type="checkbox" id="404page_hide" name="404page_hide" value="1"' . checked( true, $this->settings['404page_hide'], false ) . '/>';
483
+ echo '<label for="404page_hide" class="check"></label>' . __( 'Hide the selected page from the Pages list', '404page' ) . '&nbsp;<a class="dashicons dashicons-editor-help" href="' . $this->dc_url . '/#settings_hide_page"></a></p>';
484
+ echo '<p><span class="dashicons dashicons-info"></span>&nbsp;' . __( 'For Administrators the page is always visible.', '404page' ) . '</p>';
485
+
486
+ }
487
+
488
+
489
+ /**
490
+ * handle the settings field fire 404 error
491
+ */
492
+ function admin_fire404() {
493
+
494
+ echo '<p><input type="checkbox" id="404page_fire_error" name="404page_fire_error" value="1"' . checked( true, $this->settings['404page_fire_error'], false ) . '/>';
495
+ echo '<label for="404page_fire_error" class="check"></label>' . __( 'Send an 404 error if the page is accessed directly by its URL', '404page' ) . '&nbsp;<a class="dashicons dashicons-editor-help" href="' . $this->dc_url . '/#settings_fire_404"></a></p>';
496
+ echo '<p><span class="dashicons dashicons-info"></span>&nbsp;' . __( 'Uncheck this if you want the selected page to be accessible.', '404page' ) . '</p>';
497
+
498
+ if ( function_exists( 'wpsupercache_activate' ) ) {
499
+
500
+ echo '<p><span class="dashicons dashicons-warning"></span>&nbsp;<strong>' . __( 'WP Super Cache Plugin detected', '404page' ) . '</strong>. ' . __ ( 'If the page you selected as 404 error page is in cache, always a HTTP code 200 is sent. To avoid this and send a HTTP code 404 you have to exlcude this page from caching', '404page' ) . ' (<a href="' . admin_url( 'options-general.php?page=wpsupercache&tab=settings#rejecturi' ) . '">' . __( 'Click here', '404page' ) . '</a>).<br />(<a href="' . $this->dc_url . '/#wp_super_cache">' . __( 'Read more', '404page' ) . '</a>)</p>';
501
+
502
+ }
503
+
504
+ }
505
+
506
+
507
+ /**
508
+ * handle the settings field to force an 404 error
509
+ */
510
+ function admin_force404() {
511
+
512
+ echo '<p><input type="checkbox" id="404page_force_error" name="404page_force_error" value="1"' . checked( true, $this->settings['404page_force_error'], false ) . '/>';
513
+ echo '<label for="404page_force_error" class="check warning"></label>' . __( 'Force 404 error after loading page', '404page' ) . '&nbsp;<a class="dashicons dashicons-editor-help" href="' . $this->dc_url . '/#settings_force_404"></a></p>';
514
+ echo '<p><span class="dashicons dashicons-warning"></span>&nbsp;' . __( 'Generally this is not needed. It is not recommended to activate this option, unless it is necessary. Please note that this may cause problems with your theme.', '404page' ) . '</p>';
515
+
516
+ }
517
+
518
+
519
+ /**
520
+ * handle the settings field to stop URL guessing
521
+ */
522
+ function admin_noguess() {
523
+
524
+ echo '<p><input type="checkbox" id="404page_no_url_guessing" name="404page_no_url_guessing" value="1"' . checked( true, $this->settings['404page_no_url_guessing'], false ) . '/>';
525
+ echo '<label for="404page_no_url_guessing" class="check warning"></label>' . __( 'Disable URL autocorrection guessing', '404page' ) . '&nbsp;<a class="dashicons dashicons-editor-help" href="' . $this->dc_url . '/#settings_stop_guessing"></a></p>';
526
+ echo '<p><span class="dashicons dashicons-warning"></span>&nbsp;' . __( 'This stops WordPress from URL autocorrection guessing. Only activate, if you are sure about the consequences.', '404page' ) . '</p>';
527
+
528
+ }
529
+
530
+
531
+ /**
532
+ * handle the settings field method
533
+ */
534
+ function admin_method() {
535
+
536
+ if ( $this->settings['404page_native'] || defined( 'CUSTOMIZR_VER' ) || defined( 'ICL_SITEPRESS_VERSION' ) ) {
537
+
538
+ $dis = ' disabled="disabled"';
539
+
540
+ } else {
541
+
542
+ $dis = '';
543
+ }
544
+
545
+ echo '<p><input type="checkbox" id="404page_method" name="404page_method" value="CMP"' . checked( 'CMP', $this->settings['404page_method'], false ) . $dis . '/>';
546
+ echo '<label for="404page_method" class="check"></label>' . __( 'Activate Compatibility Mode', '404page' ) . '&nbsp;<a class="dashicons dashicons-editor-help" href="' . $this->dc_url . '/#settings_operating_method"></a></p>';
547
+ echo '<p><span class="dashicons dashicons-info"></span>&nbsp;';
548
+
549
+ if ( $this->settings['404page_native'] ) {
550
+
551
+ _e( 'This setting is not available because the Theme you are using natively supports the 404page plugin.', '404page' );
552
+ echo ' (<a href="' . $this->dc_url . '/#native_mode">' . __( 'Read more', '404page' ) . '</a>)';
553
+
554
+ } elseif ( defined( 'CUSTOMIZR_VER' ) ) {
555
+
556
+ _e( 'This setting is not availbe because the 404page Plugin works in Customizr Compatibility Mode.', '404page' );
557
+ echo ' (<a href="' . $this->dc_url . '/#special_modes">' . __( 'Read more', '404page' ) . '</a>)';
558
+
559
+ } elseif ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
560
+
561
+ _e( 'This setting is not availbe because the 404page Plugin works in WPML Mode.', '404page' );
562
+ echo ' (<a href="' . $this->dc_url . '/#special_modes">' . __( 'Read more', '404page' ) . '</a>)';
563
+
564
+ } else {
565
+
566
+ _e( 'If you are using a theme or plugin that modifies the WordPress Template System, the 404page plugin may not work properly. Compatibility Mode maybe can fix the problem. Activate Compatibility Mode only if you have any problems.', '404page' );
567
+
568
+ }
569
+
570
+ echo '</p>';
571
+
572
+ }
573
+
574
+
575
+ /**
576
+ * handle the method setting
577
+ */
578
+ function handle_method( $method ) {
579
+
580
+ if ( null === $method ) {
581
+
582
+ $method = 'STD';
583
+
584
+ }
585
+
586
+ return $method;
587
+
588
+ }
589
+
590
+
591
+ /**
592
+ * hide the 404 page from the list of pages
593
+ */
594
+
595
+ function exclude_404page( $query ) {
596
+
597
+ $pageid = $this->get_page_id();
598
+
599
+ if ( $pageid > 0 ) {
600
+
601
+ global $pagenow;
602
+
603
+ $post_type = $query->get( 'post_type' );
604
+
605
+ // as of v 2.3 we check the post_type on front end
606
+ // as of v 2.5 we also hide the page from search results on front end
607
+ if( ( is_admin() && ( 'edit.php' == $pagenow && !current_user_can( 'create_users' ) ) ) || ( ! is_admin() && ( is_search() || ( !empty( $post_type) && ( ('page' === $post_type || 'any' === $post_type) || ( is_array( $post_type ) && in_array( 'page', $post_type ) ) ) ) ) ) ) {
608
+
609
+ // as of v 2.4 we hide all translations in admin for WPML
610
+ // as of v 2.5 we hide all translations from search results on front end for WPML
611
+ if ( is_admin() || ( ! is_admin() && is_search() ) ) {
612
+
613
+ $pageids = $this->get_all_page_ids();
614
+
615
+ } else {
616
+
617
+ $pageids = array( $pageid );
618
+
619
+ }
620
+
621
+ // as of v 2.3 we add the ID of the 404 page to post__not_in
622
+ // using just $query->set() overrides existing settings but not adds a new setting
623
+ $query->set( 'post__not_in', array_merge( (array)$query->get( 'post__not_in', array() ), $pageids ) );
624
+
625
+ }
626
+
627
+ }
628
+
629
+ }
630
+
631
+
632
+ /**
633
+ * remove the 404 page from get_pages result array
634
+ */
635
+ function remove_404page_from_array( $pages, $r ) {
636
+
637
+ for ( $i = 0; $i < sizeof( $pages ); $i++ ) {
638
+
639
+ if ( $pages[$i]->ID == $this->settings['404page_page_id'] ) {
640
+
641
+ unset( $pages[$i] );
642
+ break;
643
+
644
+ }
645
+
646
+ }
647
+
648
+ return array_values( $pages );
649
+
650
+ }
651
+
652
+
653
+ /**
654
+ * create the menu entry
655
+ */
656
+ function admin_menu() {
657
+ $this->admin_handle = add_theme_page ( __( '404 Error Page', "404page" ), __( '404 Error Page', '404page' ), 'manage_options', '404pagesettings', array( $this, 'admin_page' ) );
658
+ }
659
+
660
+
661
+ /**
662
+ * add admin css file
663
+ */
664
+ function admin_css() {
665
+
666
+ if ( get_current_screen()->id == $this->admin_handle ) {
667
+
668
+ wp_enqueue_style( '404pagecss', plugins_url( 'assets/css/404page-ui.css', $this->_file ) );
669
+
670
+ }
671
+
672
+ }
673
+
674
+
675
+ /**
676
+ * add admin js files
677
+ */
678
+ function admin_js() {
679
+
680
+ wp_enqueue_script( '404pagejs', plugins_url( 'assets/js/404page.js', $this->_file ), 'jquery', $this->version, true );
681
+
682
+ wp_localize_script( '404pagejs', 'pp_404page_remove', array( 'pp_404page_dismiss_admin_notice_number' => 'pp-404page-admin-notice-1' ) );
683
+
684
+ if ( get_current_screen()->id == $this->admin_handle ) {
685
+
686
+ wp_enqueue_script( 'jquery-ui-accordion' );
687
+
688
+ wp_enqueue_script( '404page-ui', plugins_url( 'assets/js/404page-ui.js', $this->_file ), 'jquery', $this->version, true );
689
+
690
+ }
691
+
692
+ }
693
+
694
+
695
+ /**
696
+ * show admin page
697
+ */
698
+ function admin_page() {
699
+
700
+ if ( !current_user_can( 'manage_options' ) ) {
701
+
702
+ wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
703
+
704
+ }
705
+ ?>
706
+ <div class="wrap" id="pp-404page-settings">
707
+ <h1 id="pp-plugin-info-404page"><?php echo $this->plugin_name; ?> <?php _e( 'Settings', '404page' ); ?><span><a class="dashicons dashicons-wordpress" href="<?php echo $this->wp_url; ?>/" title="<?php _e( 'wordpress.org plugin directory', '404page' ); ?>"></a> <a class="dashicons dashicons-admin-home" href="http://petersplugins.com/" title="<?php _e( 'Author homepage', '404page' );?>"></a> <a class="dashicons dashicons-googleplus" href="http://g.petersplugins.com/" title="<?php _e( 'Authors Google+ Page', '404page' ); ?>"></a> <a class="dashicons dashicons-facebook-alt" href="http://f.petersplugins.com/" title="<?php _e( 'Authors facebook Page', '404page' ); ?>"></a> <a class="dashicons dashicons-book-alt" href="<?php echo $this->dc_url; ?>" title="<?php _e( 'Plugin Doc', '404page' ); ?>"></a> <a class="dashicons dashicons-editor-help" href="http://wordpress.org/support/plugin/<?php echo $this->plugin_slug; ?>/" title="<?php _e( 'Support', '404page'); ?>"></a> <a class="dashicons dashicons-admin-comments" href="http://petersplugins.com/contact/" title="<?php _e( 'Contact Author', '404page' ); ?>"></a></span></h1>
708
+ <?php settings_errors(); ?>
709
+ <form method="post" action="options.php">
710
+ <?php settings_fields( '404page_settings' ); ?>
711
+ <?php do_settings_sections( '404page_settings_section' ); ?>
712
+ <div id="pp-404page-settings-advanced">
713
+ <h3>Advanced Settings</h3>
714
+ <div>
715
+ <?php do_settings_sections( '404page_settings_section_advanced' ); ?>
716
+ </div>
717
+ </div>
718
+ <?php submit_button(); ?>
719
+ </form>
720
+ </div>
721
+ <?php
722
+ }
723
+
724
+
725
+ /**
726
+ * show admin notices
727
+ */
728
+ function admin_notices() {
729
+
730
+ // invite to follow me
731
+ if ( current_user_can( 'manage_options' ) && get_user_meta( get_current_user_id(), 'pp-404page-admin-notice-1', true ) != 'dismissed' ) {
732
+ ?>
733
+ <div class="notice is-dismissible" id="pp-404page-admin-notice-1">
734
+ <p><img src="<?php echo plugins_url( 'assets/pluginicon.png', $this->_file ); ?>" style="width: 48px; height: 48px; float: left; margin-right: 20px" /><strong><?php _e( 'Do you like the 404page plugin?', '404page' ); ?></strong><br /><?php _e( 'Follow me:', '404page' ); ?> <a class="dashicons dashicons-googleplus" href="http://g.petersplugins.com/" title="<?php _e( 'Authors Google+ Page', '404page' ); ?>"></a> <a class="dashicons dashicons-facebook-alt" href="http://f.petersplugins.com/" title="<?php _e( 'Authors facebook Page', '404page' ); ?>"></a><div class="clear"></div></p>
735
+ </div>
736
+ <?php
737
+ }
738
+
739
+ }
740
+
741
+
742
+ /**
743
+ * dismiss an admin notice
744
+ */
745
+ function dismiss_admin_notice() {
746
+
747
+ if ( isset( $_POST['pp_404page_dismiss_admin_notice'] ) ) {
748
+
749
+ update_user_meta( get_current_user_id(), $_POST['pp_404page_dismiss_admin_notice'], 'dismissed' );
750
+
751
+ }
752
+
753
+ wp_die();
754
+
755
+ }
756
+
757
+
758
+ /**
759
+ * get the id of the 404 page
760
+ * returns 0 if none is defined, returns -1 if the defined page id does not exist
761
+ */
762
+ private function get_404page_id() {
763
+
764
+ $pageid = get_option( '404page_page_id', 0 );
765
+
766
+ if ( $pageid != 0 ) {
767
+
768
+ $page = get_post( $pageid );
769
+
770
+ if ( !$page || $page->post_status != 'publish' ) {
771
+
772
+ $pageid = -1;
773
+
774
+ }
775
+
776
+ }
777
+
778
+ return $pageid;
779
+
780
+ }
781
+
782
+
783
+ /**
784
+ * get the selected method
785
+ */
786
+ private function get_404page_method() {
787
+
788
+ if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
789
+
790
+ // WPML is active
791
+ return 'CMP';
792
+
793
+ } else {
794
+
795
+ return get_option( '404page_method', 'STD' );
796
+
797
+ }
798
+
799
+ }
800
+
801
+
802
+ /**
803
+ * do we have to hide the selected 404 page from the page list?
804
+ */
805
+ private function get_404page_hide() {
806
+
807
+ return (bool)get_option( '404page_hide', false );
808
+
809
+ }
810
+
811
+
812
+ /**
813
+ * do we have to fire an 404 error if the selected page is accessed directly?
814
+ */
815
+ private function get_404page_fire_error() {
816
+
817
+ return (bool)get_option( '404page_fire_error', true );
818
+
819
+ }
820
+
821
+
822
+ /**
823
+ * do we have to force the 404 error after loading the page?
824
+ */
825
+ private function get_404page_force_error() {
826
+
827
+ return (bool)get_option( '404page_force_error', false );
828
+
829
+ }
830
+
831
+
832
+ /**
833
+ * do we have to disable the URL guessing?
834
+ */
835
+ private function get_404page_no_url_guessing() {
836
+
837
+ return (bool)get_option( '404page_no_url_guessing', false );
838
+
839
+ }
840
+
841
+
842
+ /**
843
+ * get the id of the 404 page in the current language if WPML is active
844
+ */
845
+ private function get_page_id() {
846
+
847
+ $pageid = $this->settings['404page_page_id'];
848
+
849
+ if ( $pageid > 0 ) {
850
+
851
+ if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
852
+
853
+ // WPML is active
854
+ $pageid = apply_filters( 'wpml_object_id', $pageid, 'page', true );
855
+
856
+ }
857
+
858
+ }
859
+
860
+ return $pageid;
861
+
862
+ }
863
+
864
+ /**
865
+ * get 404 pages in all available languages
866
+ * if WPML is active this function returns an array of all page ids in all available languages
867
+ * otherwise it returns the page id as array
868
+ * introduced in v 2.4
869
+ */
870
+ private function get_all_page_ids() {
871
+
872
+ if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
873
+
874
+ // WPML is active
875
+ // get an array for all translations
876
+ $pageid = $this->settings['404page_page_id'];
877
+ $pages = array( $pageid );
878
+
879
+ if ( $pageid > 0 ) {
880
+
881
+ $languages = apply_filters( 'wpml_active_languages', NULL );
882
+
883
+ if ( !empty( $languages ) ) {
884
+
885
+ foreach( $languages as $l ) {
886
+
887
+ $p = apply_filters( 'wpml_object_id', $pageid, 'page', false, $l['language_code'] );
888
+
889
+ if ( $p ) {
890
+
891
+ $pages[] = $p;
892
+
893
+ }
894
+
895
+ }
896
+
897
+ }
898
+
899
+ }
900
+
901
+ $pageids = array_unique( $pages, SORT_NUMERIC );
902
+
903
+ } else {
904
+
905
+ $pageids = array( $this->get_page_id() );
906
+
907
+ }
908
+
909
+ return $pageids;
910
+
911
+ }
912
+
913
+
914
+ /**
915
+ * fire 404page_after_404 hook to make plugin expandable
916
+ */
917
+ function do_404page_action() {
918
+
919
+ do_action( '404page_after_404' );
920
+
921
+ }
922
+
923
+
924
+ /**
925
+ * add links to plugins table
926
+ */
927
+ function add_settings_links( $links ) {
928
+
929
+ return array_merge( $links, array( '<a class="dashicons dashicons-admin-tools" href="' . admin_url( 'themes.php?page=404pagesettings' ) . '" title="' . __( 'Settings', '404page' ) . '"></a>', '<a class="dashicons dashicons-star-filled" href="https://wordpress.org/support/plugin/' . $this->plugin_slug . '/reviews/" title="' . __( 'Please rate plugin', '404page' ) . '"></a>' ) );
930
+
931
+ }
932
+
933
+
934
+ /**
935
+ * uninstall plugin
936
+ */
937
+ function uninstall() {
938
+
939
+ if( is_multisite() ) {
940
+
941
+ $this->uninstall_network();
942
+
943
+ } else {
944
+
945
+ $this->uninstall_single();
946
+
947
+ }
948
+
949
+ }
950
+
951
+
952
+ /**
953
+ * uninstall network wide
954
+ */
955
+ function uninstall_network() {
956
+
957
+ global $wpdb;
958
+ $activeblog = $wpdb->blogid;
959
+ $blogids = $wpdb->get_col( esc_sql( 'SELECT blog_id FROM ' . $wpdb->blogs ) );
960
+
961
+ foreach ($blogids as $blogid) {
962
+
963
+ switch_to_blog( $blogid );
964
+ $this->uninstall_single();
965
+
966
+ }
967
+
968
+ switch_to_blog( $activeblog );
969
+
970
+ }
971
+
972
+
973
+ /**
974
+ * uninstall for a single blog
975
+ */
976
+ function uninstall_single() {
977
+
978
+ foreach ( $this->settings as $key => $value) {
979
+
980
+ delete_option( $key );
981
+
982
+ }
983
+
984
+ }
985
+
986
+
987
+ /**
988
+ * functions for theme usage
989
+ */
990
+
991
+ // check if there's a custom 404 page set
992
+ function pp_404_is_active() {
993
+
994
+ return ( $this->settings['404page_page_id'] > 0 );
995
+
996
+ }
997
+
998
+ // activate the native theme support
999
+ function pp_404_set_native_support() {
1000
+
1001
+ $this->settings['404page_native'] = true;
1002
+
1003
+ }
1004
+
1005
+ // get the title - native theme support
1006
+ function pp_404_get_the_title() {
1007
+
1008
+ $title = '';
1009
+
1010
+ if ( $this->settings['404page_page_id'] > 0 && $this->settings['404page_native'] ) {
1011
+
1012
+ $title = get_the_title( $this->get_page_id() );
1013
+
1014
+ }
1015
+
1016
+ return $title;
1017
+
1018
+ }
1019
+
1020
+ // print title - native theme support
1021
+ function pp_404_the_title() {
1022
+
1023
+ echo $this->pp_404_get_the_title();
1024
+
1025
+ }
1026
+
1027
+ // get the content - native theme support
1028
+ function pp_404_get_the_content() {
1029
+
1030
+ $content = '';
1031
+
1032
+ if ( $this->settings['404page_page_id'] > 0 && $this->settings['404page_native'] ) {
1033
+
1034
+ $content = apply_filters( 'the_content', get_post_field( 'post_content', $this->get_page_id() ) );
1035
+
1036
+ }
1037
+
1038
+ return $content;
1039
+
1040
+ }
1041
+
1042
+ // print content - native theme support
1043
+ function pp_404_the_content() {
1044
+
1045
+ echo $this->pp_404_get_the_content();
1046
+
1047
+ }
1048
+
1049
+ }
1050
+
1051
+ }
1052
+
1053
+ ?>
inc/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden
index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden
pluginicon.png DELETED
Binary file
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === 404page - your smart custom 404 error page ===
2
  Contributors: petersplugins, smartware.cc
3
- 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.7
7
- Stable tag: 2.5
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -12,21 +12,32 @@ Custom 404 the easy way! Set any page as custom 404 error page. No coding needed
12
 
13
  == Description ==
14
 
15
- Create your custom 404 page just like any other page. Then go to 'Appearance' -> '404 Error Page' and select the created page as your custom 404 error page. That's it!
16
 
17
- = Need more information? =
18
 
19
- See [Plugin Homepage](http://petersplugins.com/free-wordpress-plugins/404page/) and [Plugin Doc](http://petersplugins.com/docs/404page/).
20
 
21
  = Why you should choose this plugin =
22
 
23
  * Different from other similar plugins the 404page plugin **does not create redirects**. That’s **quite important** because a correct code 404 is delivered which tells search engines that the page does not exist and has to be removed from the index. A redirect would result in a HTTP code 301 or 302 and the URL would remain in the search index.
24
  * Different from other similar plugins the 404page plugin **does not create additional server requests**.
25
 
26
- = Watch the video =
27
 
28
  https://www.youtube.com/watch?v=VTL07Lf0IsY
29
 
 
 
 
 
 
 
 
 
 
 
 
30
  = Do you like the 404page Plugin? =
31
 
32
  Thanks, I appreciate that. You don’t need to make a donation. No money, no beer, no coffee. Please, just [tell the world that you like what I’m doing](http://petersplugins.com/make-a-donation/)! And that’s all.
@@ -104,14 +115,15 @@ The plugin adds an action hook 404page_after_404 which you can use to add extra
104
  = Native Support =
105
  If you are a theme developer you can add native support for the 404page plugin to your theme for full control. [Read more](http://petersplugins.com/docs/404page/#theme_native_support).
106
 
107
- == Screenshots ==
108
-
109
- 1. Create your 404 Page as a normal WordPress Page
110
- 2. Define the created Page as 404 Error Page
111
- 3. Your custom 404 Error Page is shown in case of a 404 error
112
-
113
  == Changelog ==
114
 
 
 
 
 
 
 
 
115
  = 2.5 (2017-05-19) =
116
  * hide 404 page from search results on front end (if WPML is active, all languages are hidden)
117
  * do not fire a 404 in Compatibility Mode if the [DW Question & Answer plugin by DesignWall](https://www.designwall.com/wordpress/plugins/dw-question-answer/) is active and a question has no answers
@@ -178,8 +190,11 @@ If you are a theme developer you can add native support for the 404page plugin t
178
 
179
  == Upgrade Notice ==
180
 
 
 
 
181
  = 2.5 =
182
- Hhide 404 page from search results, compatibility with DW Question & Answer plugin
183
 
184
  = 2.4 =
185
  Version 2.4 fixes several issues. See [changelog](https://wordpress.org/plugins/404page/changelog/) for details.
1
  === 404page - your smart custom 404 error page ===
2
  Contributors: petersplugins, smartware.cc
3
+ 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.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
12
 
13
  == Description ==
14
 
15
+ This Plugin allows you to create your custom 404 page just like any other page using the WordPress Page Editor.
16
 
17
+ = Usage =
18
 
19
+ Create your custom 404 page just like any other page. Then go to 'Appearance' -> '404 Error Page' and select the created page as your custom 404 error page. That's it!
20
 
21
  = Why you should choose this plugin =
22
 
23
  * Different from other similar plugins the 404page plugin **does not create redirects**. That’s **quite important** because a correct code 404 is delivered which tells search engines that the page does not exist and has to be removed from the index. A redirect would result in a HTTP code 301 or 302 and the URL would remain in the search index.
24
  * Different from other similar plugins the 404page plugin **does not create additional server requests**.
25
 
26
+ = Watch the video (outdated version, new version will be created as soon as possible) =
27
 
28
  https://www.youtube.com/watch?v=VTL07Lf0IsY
29
 
30
+ = Need more information? =
31
+
32
+ See [Plugin Homepage](http://petersplugins.com/free-wordpress-plugins/404page/) and [Plugin Doc](http://petersplugins.com/docs/404page/).
33
+
34
+ == Screenshots ==
35
+
36
+ 1. Create your costom 404 Error Page as a normal WordPress Page
37
+ 2. Set the created Page as 404 Error Page
38
+ 3. Advanced Settings
39
+ 4. Advanced Settings with WPML plugin installed (Compatibility Mode is not available, because the 404page plugin automatically switches to WMPL mode)
40
+
41
  = Do you like the 404page Plugin? =
42
 
43
  Thanks, I appreciate that. You don’t need to make a donation. No money, no beer, no coffee. Please, just [tell the world that you like what I’m doing](http://petersplugins.com/make-a-donation/)! And that’s all.
115
  = Native Support =
116
  If you are a theme developer you can add native support for the 404page plugin to your theme for full control. [Read more](http://petersplugins.com/docs/404page/#theme_native_support).
117
 
 
 
 
 
 
 
118
  == Changelog ==
119
 
120
+ = 3.0 (2017-07-05) =
121
+ * new feature to force 404 error after loading page
122
+ * new feature to disable URL autocorrection guessing
123
+ * finally removed Polylang stuff disabled in 2.4
124
+ * redesigned admin interface
125
+ * code improvement
126
+
127
  = 2.5 (2017-05-19) =
128
  * hide 404 page from search results on front end (if WPML is active, all languages are hidden)
129
  * do not fire a 404 in Compatibility Mode if the [DW Question & Answer plugin by DesignWall](https://www.designwall.com/wordpress/plugins/dw-question-answer/) is active and a question has no answers
190
 
191
  == Upgrade Notice ==
192
 
193
+ = 3.0 =
194
+ new features added to force 404 error after loading page and to disable URL autocorrection guessing, plus further enhancements
195
+
196
  = 2.5 =
197
+ Hide 404 page from search results, compatibility with DW Question & Answer plugin
198
 
199
  = 2.4 =
200
  Version 2.4 fixes several issues. See [changelog](https://wordpress.org/plugins/404page/changelog/) for details.
uninstall.php CHANGED
@@ -1,12 +1,24 @@
1
  <?php
2
- // 404page uninstall
3
 
4
- if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) || ! WP_UNINSTALL_PLUGIN || dirname( WP_UNINSTALL_PLUGIN ) != dirname( plugin_basename( __FILE__ ) ) ) {
5
- status_header( 404 );
6
- exit;
7
- }
8
-
9
- include_once plugin_dir_path( __FILE__ ) . '404page.php';
10
 
11
- $smart404page->uninstall();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  ?>
1
  <?php
 
2
 
3
+ /**
4
+ * The 404page Plugin Uninstall
5
+ */
6
+
 
 
7
 
8
+ // If this file is called directly, abort
9
+ if ( ! defined( 'WPINC' ) ) {
10
+ die;
11
+ }
12
+
13
+
14
+ // If this is somehow accessed withou plugin uninstall is requested, abort
15
+ if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) || ! WP_UNINSTALL_PLUGIN || dirname( WP_UNINSTALL_PLUGIN ) != dirname( plugin_basename( __FILE__ ) ) ) {
16
+ die;
17
+ }
18
+
19
+
20
+ // Load plugin file and start uninstall
21
+ include_once plugin_dir_path( __FILE__ ) . '404page.php';
22
+ $pp_404page->uninstall();
23
+
24
  ?>