permalinks = (bool) get_option('permalink_structure');
$this->table = $GLOBALS['wpdb']->prefix . '410_links';
add_action( 'plugins_loaded', array( $this, 'upgrade_check' ) );
if( is_admin() )
add_action( 'admin_menu', array( $this, 'settings_menu' ) );
else
add_action( 'template_redirect', array( $this, 'check_for_410' ) );
// these could theoretically happen both with/without is_admin()
add_action('wp_insert_post', array( $this, 'note_inserted_post' ));
}
private function install_table() {
// remember, two spaces after PRIMARY KEY otherwise WP borks
$sql = "CREATE TABLE $this->table (
gone_id MEDIUMINT unsigned NOT NULL AUTO_INCREMENT,
gone_key VARCHAR(512) NOT NULL,
gone_regex VARCHAR(512) NOT NULL,
is_404 SMALLINT(1) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (gone_id),
KEY is_404 (is_404)
);";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
private function get_links(){
global $wpdb;
return $wpdb->get_results( "SELECT gone_key, gone_regex FROM $this->table WHERE is_404 = 0", OBJECT_K ); // indexed by gone_key
}
private function max_404_list_length() {
return get_option( 'deletepages_410_max_404s', 50 );
}
private function get_404s(){
global $wpdb;
$this->concat_404_list();
return $wpdb->get_results( "SELECT gone_key, gone_regex FROM $this->table WHERE is_404 = 1 ORDER BY gone_id DESC", OBJECT_K ); // indexed by gone_key
}
private function add_link( $key, $is_404 = false ){ // just supply the link
global $wpdb;
// 404 logging enabled?
if( $is_404 && $this->max_404_list_length() == 0 )
return;
// build regex
$parts = preg_split( '/(\*)/', $key, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
foreach( $parts as &$part ) if( '*' != $part )
$part = preg_quote( $part, '|' );
$parts = str_replace( '*', '.*', $parts );
$regex = '|^' . implode( '', $parts ) . '$|i';
// avoid duplicates - messy but MySQL doesn't allow url-length unique keys
if( $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM `$this->table` WHERE `gone_key` = %s", $key ) ) )
return 0;
$wpdb->insert( $this->table, array( 'gone_key' => $key, 'gone_regex' => $regex, 'is_404' => intval( $is_404 ) ) );
// Don't let 404 list grow forever
if( $is_404 )
$this->concat_404_list();
}
private function concat_404_list() {
global $wpdb;
$n = intval( $wpdb->get_var( "SELECT COUNT(*) FROM `$this->table` WHERE `is_404` = 1" ) - $this->max_404_list_length() );
if( $n > 0 )
$wpdb->query( "DELETE FROM `$this->table` WHERE is_404 = 1 ORDER BY gone_id LIMIT $n" );
}
private function convert_404( $key ) {
global $wpdb;
return $wpdb->query( $wpdb->prepare( "UPDATE `$this->table` SET is_404 = 0 WHERE `gone_key` = %s LIMIT 1", $key ) );
}
private function remove_link( $key ){
global $wpdb;
return $wpdb->query( $wpdb->prepare( "DELETE FROM $this->table WHERE gone_key = %s", array( $key ) ) );
}
function upgrade_check() {
$options_version = get_option( 'deletepages_410_options_version', 0 );
if( $options_version == self::db_version ) // nothing to do
return;
// last db change was in version 5
if( $options_version < 5 )
$this->install_table();
if( $options_version < 3 ) {
$old_links = get_option( 'deletepages_410_links_list', array() );
$new_links = array(); // just a simple array of links
if( 0 == $options_version ) // links were stored just as links
$new_links = array_map( 'rawurldecode', $old_links );
elseif( 1 == $options_version ) // links were stored as array( link => regex ), We only need the link
$new_links = array_map( 'rawurldecode', array_keys( $old_links ) );
else // moved to using the database in db_version 3
$new_links = array_keys( $old_links );
foreach( $new_links as $link )
$this->add_link( $link );
delete_option( 'deletepages_410_links_list' ); // remove old option
}
update_option( 'deletepages_410_options_version', self::db_version );
}
function settings_menu() {
add_submenu_page('plugins.php', '410 Deleted Pages', '410 Deleted Pages', 'manage_options', 'deletepages_410_settings', array( $this, 'settings_page') );
}
function settings_page() {
$links = $this->get_links();
$logged_404s = $this->get_404s();
$links_to_add = array();
// Entries to delete
if( isset( $_POST['delete-from-410-list'] ) && !empty( $_POST['old_links_to_remove'] ) ) {
check_admin_referer( 'deletepages-410-settings' );
foreach( $_POST['old_links_to_remove'] as $key ) {
$key = stripslashes( $key );
if( isset( $links[$key] ) ) {
$this->remove_link( $key );
unset( $links[$key] );
}
}
}
// Entries to add, either manually or from 404 list
else if ( isset( $_POST['add-to-410-list'] ) ) {
check_admin_referer( 'deletepages-410-settings' );
$failed_to_add = array();
if( !empty( $_POST['links_to_add'] ) ) {
foreach( preg_split( '/(\r?\n)+/', $_POST['links_to_add'], -1, PREG_SPLIT_NO_EMPTY ) as $link ) {
$link = stripslashes( $link );
if( $this->is_valid_url( $link ) ) {
$this->add_link( $link );
}
else {
$failed_to_add[] = '' . htmlspecialchars( $link ) . '';
}
}
}
if( !empty( $_POST['add_404s'] ) ) {
foreach( $_POST['add_404s'] as $link ) {
$link = stripslashes( $link );
$this->convert_404( $link );
}
}
// Update lists
$links = $this->get_links();
$logged_404s = $this->get_404s();
if( $failed_to_add )
echo '
The following entries could not be recognised as URLs that your WordPress site handles, and were not added to the list. This can be because the domain name and path does not match that of your WordPress site, or because pretty permalinks are disabled.
- ' . implode( '
- ', $failed_to_add ) .'
Options updated.
Warning: It seems that a caching/performance plugin is active on this site. This plugin has only been tested with the following caching plugins:
Other caching plugins may cache responses to requests for pages that have been removed, in which case this plugin will not be able to intercept the requests and issue a 410 response header.
This plugin will issue a HTTP 410 response to all pages on the list or just the pages that returns 404 page not found. This informs robots that the requested page has been permanently removed, and that they should stop trying to access it.
A 410 response will only be issued if WordPress has not found something valid to display for the requested URL.
By default, the plugin issues the following plain-text message as part of the 410 response: Sorry, the page you requested has been permanently removed.
410.php has been detected in your theme directory. This file will be used to display 410 responses. To revert back to the default message, remove the file from your theme directory.';
else
echo 'If you would like to use your own template instead, simply place a file called 410.php in your theme directory, containing your template. Have a look at your theme\'s 404.php template to see what it should look like.