_file = $file; $this->plugin_name = '404page'; $this->plugin_slug = '404page'; $this->version = '3.1'; $this->get_settings(); $this->load(); } /** * get all settings * except 404page_method * the 404page_method setting is set in function set_mode() because it may be too early here and not everything is loaded properly */ private function get_settings() { $this->settings = array(); $this->settings['404page_page_id'] = $this->get_404page_id(); $this->settings['404page_hide'] = $this->get_404page_hide(); $this->settings['404page_fire_error'] = $this->get_404page_fire_error(); $this->settings['404page_force_error'] = $this->get_404page_force_error(); $this->settings['404page_no_url_guessing'] = $this->get_404page_no_url_guessing(); $this->settings['404page_native'] = false; } /** * Load * runs the init() function on firing of init action to ensure everything is loaded properly */ private function load() { $this->wp_url = 'https://wordpress.org/plugins/' . $this->plugin_slug; $this->my_url = 'http://petersplugins.com/free-wordpress-plugins/' . $this->plugin_slug; $this->dc_url = 'http://petersplugins.com/docs/' . $this->plugin_slug; add_action( 'init', array( $this, 'add_text_domain' ) ); add_action( 'init', array( $this, 'init' ) ); add_action( 'admin_notices', array( $this, 'admin_notices' ) ); add_action( 'wp_ajax_pp_404page_dismiss_admin_notice', array( $this, 'dismiss_admin_notice' ) ); } /** * do plugin init * this runs after init action has fired to ensure everything is loaded properly */ function init() { // as of v 2.2 always call set_mode // as of v 2.4 we do not need to add an init action hook if ( !is_admin() && $this->settings['404page_page_id'] > 0 ) { // as of v 3.0 we once check if there's a 404 page set and not in all functions separately $this->set_mode(); add_action( 'pre_get_posts', array ( $this, 'exclude_404page' ) ); add_filter( 'get_pages', array ( $this, 'remove_404page_from_array' ), 10, 2 ); // Stop URL guessing if activated if ( $this->settings['404page_no_url_guessing'] ) { add_filter( 'redirect_canonical' ,array ( $this, 'no_url_guessing' ) ); } } else { add_action( 'admin_init', array( $this, 'admin_init' ) ); add_action( 'admin_menu', array( $this, 'admin_menu' ) ); add_action( 'admin_head', array( $this, 'admin_style' ) ); add_filter( 'plugin_action_links_' . plugin_basename( $this->_file ), array( $this, 'add_settings_links' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'admin_js' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'admin_css' ) ); // Remove 404 page from post list if activated if ( $this->settings['404page_hide'] and $this->settings['404page_page_id'] > 0 ) { add_action( 'pre_get_posts' ,array ( $this, 'exclude_404page' ) ); } } } /** * add text domain */ function add_text_domain() { load_plugin_textdomain( '404page' ); } /** * init filters */ function set_mode() { $this->settings['404page_method'] = $this->get_404page_method(); if ( defined( 'CUSTOMIZR_VER' ) ) { // Customizr Compatibility Mode // @since 3.1 add_filter( 'body_class', array( $this, 'add_404_body_class_customizr_mode' ) ); add_filter( 'tc_404_header_content', array( $this, 'show404title_customizr_mode' ), 999 ); add_filter( 'tc_404_content', array( $this, 'show404_customizr_mode' ), 999 ); add_filter( 'tc_404_selectors', array( $this, 'show404articleselectors_customizr_mode' ), 999 ); } elseif ( $this->settings['404page_method'] != 'STD' ) { // Compatibility Mode // 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 add_filter( 'the_posts', array( $this, 'show404_compatiblity_mode' ), 999 ); // 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 add_filter( 'dwqa_prepare_answers', array( $this, 'remove_show404_compatiblity_mode' ), 999 ); } else { // Standard Mode add_filter( '404_template', array( $this, 'show404_standard_mode' ), 999 ); if ( $this->settings['404page_fire_error'] ) { add_action( 'template_redirect', array( $this, 'do_404_header_standard_mode' ) ); } } } /** * show 404 page * Standard Mode */ function show404_standard_mode( $template ) { global $wp_query; if ( ! $this->settings['404page_native'] ) { $wp_query = null; $wp_query = new WP_Query(); $wp_query->query( 'page_id=' . $this->get_page_id() ); $wp_query->the_post(); $template = get_page_template(); rewind_posts(); add_filter( 'body_class', array( $this, 'add_404_body_class' ) ); } $this->maybe_force_404(); $this->do_404page_action(); return $template; } /** * show 404 page * Compatibility Mode */ function show404_compatiblity_mode( $posts ) { // remove the filter so we handle only the first query - no custom queries remove_filter( 'the_posts', array( $this, 'show404_compatiblity_mode' ), 999 ); $pageid = $this->get_page_id(); if ( ! $this->settings['404page_native'] ) { if ( empty( $posts ) && is_main_query() && !is_robots() && !is_home() && !is_feed() && !is_search() && !is_archive() && ( !defined('DOING_AJAX') || !DOING_AJAX ) ) { // 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 $this->postid = $pageid; // as of v 2.4 we use the the_posts filter instead of posts_results // therefore we have to reset $wp_query // resetting $wp_query also forces us to remove the pre_get_posts action plus the get_pages filter remove_action( 'pre_get_posts', array ( $this, 'exclude_404page' ) ); remove_filter( 'get_pages', array ( $this, 'remove_404page_from_array' ), 10, 2 ); global $wp_query; $wp_query = null; $wp_query = new WP_Query(); $wp_query->query( 'page_id=' . $pageid ); $wp_query->the_post(); $this->template = get_page_template(); $posts = $wp_query->posts; $wp_query->rewind_posts(); add_action( 'wp', array( $this, 'do_404_header' ) ); add_filter( 'body_class', array( $this, 'add_404_body_class' ) ); add_filter( 'template_include', array( $this, 'change_404_template' ), 999 ); $this->maybe_force_404(); $this->do_404page_action(); } elseif ( 1 == count( $posts ) && 'page' == $posts[0]->post_type ) { // Do a 404 if the 404 page is opened directly if ( $this->settings['404page_fire_error'] ) { $curpageid = $posts[0]->ID; if ( defined( 'ICL_SITEPRESS_VERSION' ) ) { // WPML is active - get the post ID of the default language global $sitepress; $curpageid = apply_filters( 'wpml_object_id', $curpageid, 'page', $sitepress->get_default_language() ); $pageid = apply_filters( 'wpml_object_id', $pageid, 'page', $sitepress->get_default_language() ); } elseif ( defined( 'POLYLANG_VERSION' ) ) { // Polylang is active - get the post ID of the default language $curpageid = pll_get_post( $curpageid, pll_default_language() ); $pageid = pll_get_post( $pageid, pll_default_language() ); } if ( $pageid == $curpageid ) { add_action( 'wp', array( $this, 'do_404_header' ) ); add_filter( 'body_class', array( $this, 'add_404_body_class' ) ); $this->maybe_force_404(); $this->do_404page_action(); } } } } else { $this->maybe_force_404(); $this->do_404page_action(); } return $posts; } /** * for DW Question & Answer plugin * this function is called by the dwqa_prepare_answers filter */ function remove_show404_compatiblity_mode( $args ) { remove_filter( 'the_posts', array( $this, 'show404_compatiblity_mode' ), 999 ); return $args; } /** * this function overrides the page template in compatibilty mode */ function change_404_template( $template ) { // 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 $new_template = locate_template( array( $this->template ) ); if ( '' != $new_template ) { return $new_template ; } return $template; } /** * send 404 HTTP header * Standard Mode */ function do_404_header_standard_mode() { if ( is_page() && get_the_ID() == $this->settings['404page_page_id'] && !is_404() ) { status_header( 404 ); nocache_headers(); $this->maybe_force_404(); $this->do_404page_action(); } } /** * send 404 HTTP header * Compatibility Mode */ function do_404_header() { // remove the action so we handle only the first query - no custom queries remove_action( 'wp', array( $this, 'do_404_header' ) ); status_header( 404 ); nocache_headers(); } /** * add body classes */ function add_404_body_class( $classes ) { // as of v 3.1 we first check if the class error404 already exists if ( ! in_array( 'error404', $classes ) ) { $classes[] = 'error404'; } // debug class // @since 3.1 $debug_class = 'pp404-'; if ( $this->settings['404page_native'] ) { $debug_class .= 'native'; } elseif ( defined( 'CUSTOMIZR_VER' ) ) { $debug_class .= 'customizr'; } elseif ( defined( 'ICL_SITEPRESS_VERSION' ) ) { $debug_class .= 'wpml'; } elseif ( $this->settings['404page_method'] != 'STD' ) { $debug_class .= 'wpml'; } else { $debug_class .= 'std'; } $classes[] = $debug_class; return $classes; } /** * add body classes customizr mode * @since 3.1 */ function add_404_body_class_customizr_mode( $classes ) { if ( is_404() ) { $classes = $this->add_404_body_class( $classes ); } return $classes; } /** * show title * Customizr Compatibility Mode */ function show404title_customizr_mode( $title ) { if ( ! $this->settings['404page_native'] ) { return '
'; } /** * handle the settings field hide */ function admin_hide() { echo '
settings['404page_hide'], false ) . '/>';
echo '' . __( 'Hide the selected page from the Pages list', '404page' ) . '
';
echo ' ' . __( 'For Administrators the page is always visible.', '404page' ) . '
settings['404page_fire_error'], false ) . '/>';
echo '' . __( 'Send an 404 error if the page is accessed directly by its URL', '404page' ) . '
';
echo ' ' . __( 'Uncheck this if you want the selected page to be accessible.', '404page' );
if ( function_exists( 'wpsupercache_activate' ) ) {
echo '
' . __( 'WP Super Cache Plugin detected', '404page' ) . '. ' . __ ( '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' ) . ' (' . __( 'Click here', '404page' ) . ').
(' . __( 'Read more', '404page' ) . ')';
}
echo '
settings['404page_force_error'], false ) . '/>';
echo '' . __( 'Force 404 error after loading page', '404page' ) . '
';
echo ' ' . __( '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' ) . '
settings['404page_no_url_guessing'], false ) . '/>';
echo '' . __( 'Disable URL autocorrection guessing', '404page' ) . '
';
echo ' ' . __( 'This stops WordPress from URL autocorrection guessing. Only activate, if you are sure about the consequences.', '404page' ) . '
settings['404page_method'], false ) . $dis . '/>';
echo '' . __( 'Activate Compatibility Mode', '404page' ) . '
';
echo ' ';
if ( $this->settings['404page_native'] ) {
_e( 'This setting is not available because the Theme you are using natively supports the 404page plugin.', '404page' );
echo ' (' . __( 'Read more', '404page' ) . ')';
} elseif ( defined( 'CUSTOMIZR_VER' ) ) {
_e( 'This setting is not availbe because the 404page Plugin works in Customizr Compatibility Mode.', '404page' );
echo ' (' . __( 'Read more', '404page' ) . ')';
} elseif ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
_e( 'This setting is not availbe because the 404page Plugin works in WPML Mode.', '404page' );
echo ' (' . __( 'Read more', '404page' ) . ')';
} else {
_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' );
}
echo '