Skip to content

Instantly share code, notes, and snippets.

@jotazzu
Last active January 31, 2024 10:53
Show Gist options
  • Select an option

  • Save jotazzu/e9571973ad91877eb9e77839ca9e29c0 to your computer and use it in GitHub Desktop.

Select an option

Save jotazzu/e9571973ad91877eb9e77839ca9e29c0 to your computer and use it in GitHub Desktop.
This class allows to use WordPress plugin Redirection to add/remove redirects programmatically. It should be included in a custom plugin as it only works in the WP backend.
<?php
/**
* Creates and removes redirects for a post slug
*
* Creates and removes entries in the redirect list of plugin 'Redirection'.
*
* @link https://gist.github.com/jotazzu
* @since 1.0.1
*
* @package Programmable_Redirects
* @subpackage Programmable_Redirects
*/
/**
* Creates and removes redirects for a post slug
*
* Creates and removes entries in the redirect list of plugin 'Redirection'.
*
* @since 1.0.1
* @package Programmable_Redirects
* @subpackage Programmable_Redirects
* @author Josh Taubriler
*/
class Programmable_Redirects {
/**
* Create a new redirection group if not exists using the PHP API of plugin Redirection.
* Returns the ID of the redirection group if Redirection API is available and the group exists
* or has successfully been created.
*
* @param string $redir_group_name Name of the redirection group to check or create if not exists.
*
* @return int|WP_Error. ID of the found redirection group else WP_Error.
*
* @since 1.0.1
*/
public static function add_redirection_group( $redir_group_name = '' ) {
// Check if API of plugin Redirection is available!
if ( !method_exists( 'Red_Group', 'get_all') ) { return new WP_Error( 'programmable_redirection_redirects', "Method 'Red_Group::get_all()' of plugin Redirector does not exist in " . __METHOD__ ); }
if ( !method_exists( 'Red_Group', 'create' ) ) { return new WP_Error( 'programmable_redirection_redirects', "Method 'Red_Group::create()' of plugin Redirector does not exist in " . __METHOD__ ); }
if ( !method_exists( 'Red_Group', 'get_id' ) ) { return new WP_Error( 'programmable_redirection_redirects', "Method 'Red_Group::get_id()' of plugin Redirector does not exist in " . __METHOD__ ); }
if ($redir_group_name != '') {
$group_filter = array(
'filterBy' => [
'name' => $redir_group_name,
],
);
$redir_groups = Red_Group::get_all( $group_filter );
if ( empty($redir_groups) ) {
// Create a redirect group
$group_obj = Red_Group::create( $redir_group_name, $module_id=1 );
if ( $group_obj !== false) {
return $group_obj->get_id();
} else {
return new WP_Error( 'programmable_redirection_redirects', "Creating new redirection GROUP '{$redir_group_name}' has failed in " . __METHOD__ );;
}
}
return $redir_groups[0]['id'];
}
return new WP_Error( 'programmable_redirection_redirects', "No group name provided for creating a new redirection GROUP: \$redir_group_name='{$redir_group_name}' in " . __METHOD__ );
}
/**
* Retrieve existing redirects for the given post.
*
* @param WP_Post $post The post object or ID.
*
* @return $redir_items Array|WP_Error An (empty) array with already existing redirects or WP_Error in case of failure.
*
* @since 1.0.1
*/
public static function get_redirection_redirects( $post ) {
// Check if API of plugin Redirection is available!
if ( !method_exists( 'Red_Item', 'get_filtered') ) { return new WP_Error( 'programmable_redirection_redirects', "Method 'Red_Item::get_filtered()' of plugin Redirector does not exist in " . __METHOD__ ); }
$post_relative_url = str_replace( home_url(), '', get_permalink( $post ) );
$post_relative_url = rtrim( $post_relative_url, '/' );
// With no valid value the filter would find all existing redirections
if ( $post_relative_url == '') { return new WP_Error( 'programmable_redirection_redirects', "\$post_relative_url is empty in " . __METHOD__ ); }
$redir_filter_args = array(
'direction' => 'asc',
'per_page' => '200',
'filterBy' => [
'match' => 'url',
'url-match' => 'plain',
'url' => $post_relative_url,
'action' => 'url',
],
);
$redir_filter_result = Red_Item::get_filtered( $redir_filter_args );
$redir_items = $redir_filter_result['items'];
foreach ( $redir_items as $key => $redir_item ) {
// Check for precise match of URL as the filter uses SQL 'LIKE' for compare
if ( strcmp($post_relative_url, $redir_item['match_url']) != 0 ) {
unset( $redir_items[$key] );
}
}
return array_values( $redir_items ); // reindex the array
}
/**
* Create a new redirection entry using the PHP API of plugin Redirection.
* Store the new entry in the group given as parameter.
*
* @param WP_Post $post The post object or ID.
* @param string $redirect_to_link New link path with query params (same host name may be omitted).
* @param int $redir_status_code HTTP status code to be returned with the redirect.
* @param string $redir_group_name Name of the group where the redirect will be listed in the group admin page of plugin Redirection.
*
* @return $redir_item Array|WP_Error An array with the properties of a newly created redirect or WP_Error in case of failure.
*
* @since 1.0.1
*/
public static function create_redirection_redirect( $post, $redirect_to_link, $redir_status_code, $redir_group_name = '' ) {
// Check if API of plugin Redirection is available!
if ( !method_exists( 'Red_Group', 'get_all') ) { return new WP_Error( 'programmable_redirection_redirects', "Method 'Red_Group::get_all()' of plugin Redirector does not exist in " . __METHOD__ ); }
if ( !method_exists( 'Red_Item' , 'create' ) ) { return new WP_Error( 'programmable_redirection_redirects', "Method 'Red_Item::create()' of plugin Redirector does not exist in " . __METHOD__ ); }
$redir_group_id = 0;
if ($redir_group_name != '') {
$group_filter = array(
'filterBy' => [
'name' => $redir_group_name,
],
);
$redir_groups = Red_Group::get_all( $group_filter );
if ( count($redir_groups) > 0 ) {
$redir_group_id = $redir_groups[0]['id'];
}
}
$post_relative_url = str_replace( home_url(), '', get_permalink( $post ) );
$redir_args = array(
//'status' => 'enabled', // default: enabled
//'position' => ??, // defines the order how matching redirections are evaluated, added after the last position in the group
'match_data' => [
'source' => [
//'flag_regex' => false, // default: false
'flag_query' => 'ignore', // default: 'exact'
//'flag_case' => false, // default: false
'flag_trailing' => true, // default: false
],
//'options' => [
// 'log_exclude' => false, // default: false
//],
],
//'regex' => false, // default: false
'url' => $post_relative_url,
'match_type' => 'url',
'group_id' => $redir_group_id,
'action_type' => 'url',
'action_code' => $redir_status_code,
'action_data' => [ // available keys can be found as the name of classes in folder /redirection/matches which implement abtract class /redirection/models/match.php
'url' => $redirect_to_link,
],
);
$redir_item = Red_Item::create( $redir_args );
return $redir_item;
}
/**
* Remove all redirection entries for a post using the PHP API of plugin Redirection.
*
* @param WP_Post $post The post object or ID.
*
* @return void
*
* @since 1.0.1
*/
public static function remove_redirection_redirect( $post ) {
// Check if API of plugin Redirection is available!
if ( !method_exists( 'Red_Item' , 'get_by_id' ) ) { return new WP_Error( 'programmable_redirection_redirects', "Method 'Red_Item::get_by_id()' of plugin Redirector does not exist in " . __METHOD__ ); }
if ( !method_exists( 'Red_Item' , 'delete' ) ) { return new WP_Error( 'programmable_redirection_redirects', "Method 'Red_Item::delete()' of plugin Redirector does not exist in " . __METHOD__ ); }
$redir_items = self::get_redirection_redirects( $post );
if ( $redir_items instanceof WP_Error ) { return $redir_items; }
if ( empty($redir_items) || !is_array($redir_items) ) { return; }
foreach ( $redir_items as $redir_item) {
$redir_obj = Red_Item::get_by_id( $redir_item['id'] );
if ( $redir_obj instanceof Red_Item) {
$redir_obj->delete();
}
}
}
}
@jotazzu
Copy link
Author

jotazzu commented Jan 26, 2024

Hi @stilografico,
I had the problem too. When hooking into the status change actions it's to late, the post is already saved and function get_permalink() fails. As I use this class in a cron run, I simply can create the redirect before the changes are saved.

So, if you want to create a redirect when the update button in the post edit screen is clicked I recommend to use the action hook 'pre_post_update'. At this point the post is still published and get_permalink() should return proper results.

@stilografico
Copy link

@jotazzu thank you!
Nice solution, I'm going to try it, seems definitely more reliable than using post_name

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment