<?php
class Red_Monitor {
private $monitor_group_id;
private $updated_posts = array();
private $monitor_types = array();
private $associated = '';
public function __construct( $options ) {
$this->monitor_types = apply_filters( 'redirection_monitor_types', isset( $options['monitor_types'] ) ? $options['monitor_types'] : array() );
if ( count( $this->monitor_types ) > 0 && $options['monitor_post'] > 0 ) {
$this->monitor_group_id = intval( $options['monitor_post'], 10 );
$this->associated = isset( $options['associated_redirect'] ) ? $options['associated_redirect'] : '';
// Only monitor if permalinks enabled
if ( get_option( 'permalink_structure' ) ) {
add_action( 'pre_post_update', array( $this, 'pre_post_update' ), 10, 2 );
add_action( 'post_updated', array( $this, 'post_updated' ), 11, 3 );
add_filter( 'redirection_remove_existing', array( $this, 'remove_existing_redirect' ) );
add_filter( 'redirection_permalink_changed', array( $this, 'has_permalink_changed' ), 10, 3 );
if ( in_array( 'trash', $this->monitor_types ) ) {
add_action( 'wp_trash_post', array( $this, 'post_trashed' ) );
}
}
}
}
public function remove_existing_redirect( $url ) {
Red_Item::disable_where_matches( $url );
}
public function can_monitor_post( $post, $post_before ) {
// Check this is for the expected post
if ( ! isset( $post->ID ) || ! isset( $this->updated_posts[ $post->ID ] ) ) {
return false;
}
// Don't do anything if we're not published
if ( $post->post_status !== 'publish' || $post_before->post_status !== 'publish' ) {
return false;
}
$type = get_post_type( $post->ID );
if ( ! in_array( $type, $this->monitor_types ) ) {
return false;
}
return true;
}
/**
* Called when a post has been updated - check if the slug has changed
*/
public function post_updated( $post_id, $post, $post_before ) {
if ( isset( $this->updated_posts[ $post_id ] ) && $this->can_monitor_post( $post, $post_before ) ) {
$this->check_for_modified_slug( $post_id, $this->updated_posts[ $post_id ] );
}
}
/**
* Remember the previous post permalink
*/
public function pre_post_update( $post_id, $data ) {
$this->updated_posts[ $post_id ] = get_permalink( $post_id );
}
public function post_trashed( $post_id ) {
$data = array(
'url' => wp_parse_url( get_permalink( $post_id ), PHP_URL_PATH ),
'action_data' => array( 'url' => '/' ),
'match_type' => 'url',
'action_type' => 'url',
'action_code' => 301,
'group_id' => $this->monitor_group_id,
'status' => 'disabled',
);
// Create a new redirect for this post, but only if not draft
if ( $data['url'] !== '/' ) {
Red_Item::create( $data );
}
}
/**
* Changed if permalinks are different and the before wasn't the site url (we don't want to redirect the site URL)
*/
public function has_permalink_changed( $result, $before, $after ) {
// Check it's not redirecting from the root
if ( $this->get_site_path() === $before || $before === '/' ) {
return false;
}
// Are the URLs the same?
if ( $before === $after ) {
return false;
}
return true;
}
private function get_site_path() {
$path = wp_parse_url( get_site_url(), PHP_URL_PATH );
if ( $path ) {
return rtrim( $path, '/' ) . '/';
}
return '/';
}
public function check_for_modified_slug( $post_id, $before ) {
$after = wp_parse_url( get_permalink( $post_id ), PHP_URL_PATH );
$before = wp_parse_url( esc_url( $before ), PHP_URL_PATH );
if ( apply_filters( 'redirection_permalink_changed', false, $before, $after ) ) {
do_action( 'redirection_remove_existing', $after, $post_id );
$data = array(
'url' => $before,
'action_data' => array( 'url' => $after ),
'match_type' => 'url',
'action_type' => 'url',
'action_code' => 301,
'group_id' => $this->monitor_group_id,
);
// Create a new redirect for this post
$new_item = Red_Item::create( $data );
if ( ! is_wp_error( $new_item ) ) {
do_action( 'redirection_monitor_created', $new_item, $before, $post_id );
if ( ! empty( $this->associated ) ) {
// Create an associated redirect for this post
$data['url'] = trailingslashit( $data['url'] ) . ltrim( $this->associated, '/' );
$data['action_data'] = array( 'url' => trailingslashit( $data['action_data']['url'] ) . ltrim( $this->associated, '/' ) );
Red_Item::create( $data );
}
}
return true;
}
return false;
}
}