[code snippet] live-replace URLs before serving page
-
I wrote a dirty code snippet to live-replace URLs in content before a page is served. I’m posting it here because I want everyone to take shots at it and help this become a snippet that works for all situations. Obviously, the best thing would be to actually find/replace strings in the database, however this opens us up to corruption risk and other time-consuming cleanup if it screws up.
This lets the Redirection plugin continue handling uncaught (i.e. external) redirects AND live-fixes things at render-time (which is horrible if you’re not caching, but then again, what kind of animal are you if you’re not caching to some degree? LOL)
function replace_old_links_in_content($content) {
// Ensure Redirection plugin is active; if not, BAIL EARLY
if (!is_plugin_active('redirection/redirection.php')) {
return $content;
}
// FOR DEBUGGING, if you need it:
// Define allowed post types and specific post IDs (set to null to apply to all)
$allowed_cpts = []; // Change to post types you want; [] = all/any; ['post'] = only posts
$allowed_post_id = []; // Change to specific post IDs for testing; [] = all/any; [1,2] = only post ID 1 and 2
// END DEBUGGING
// Get the current post object
global $post;
if (!$post) {
return $content;
}
// Check if the current post matches the CPTs or the allowed post ID
if (!empty($allowed_cpts) && !in_array($post->post_type, $allowed_cpts)) {
return $content;
}
if (!empty($allowed_post_ids) && !in_array($post->ID, (array) $allowed_post_ids)) {
return $content;
}
// @TODO I know I shouldn't do this so teach me the right way for this plugin
global $wpdb;
$redirects = $wpdb->get_results("SELECT url as source, action_data as target FROM {$wpdb->prefix}redirection_items WHERE action_type='url' and match_type='url'");
if ($redirects) {
foreach ($redirects as $redirect) {
// @TODO this all needs to be rewritten to take all the pattern matching into consideration (or use the API). I told you this is a dirty snippet.
//
$old_path = trim($redirect->source, "/"); // Remove leading/trailing slashes
$new_url = esc_url($redirect->target);
// Generate the full site URL dynamically
$site_url = home_url("/{$old_path}/");
// Create regex to match all possible variations of the old URL
$pattern = '~https?://(www\.)?' . preg_quote(parse_url($site_url, PHP_URL_HOST) . parse_url($site_url, PHP_URL_PATH), '~') . '?(/)?~i';
// Perform regex replacement
$content = preg_replace($pattern, $new_url, $content);
}
}
return $content;
}
add_filter('the_content', 'replace_old_links_in_content', 20);Implementation:
- do not use on a production site
- try it using the Code Snippets plugin:
- create a new snippet, copy/paste this into the snippet with title INFRASTRUCTURE | LIVE-fix old URLs based on Redirection plugin rules , set it to run on front-end only, Save+Activate
- go to some pages that used to have old URLs – they should now be rewritten to the new/correct URLs
Known Flaws:
- Shouldn’t directly access the database – I want help with this
- Needs a more careful, less greedy approach to matching i.e. within links only
- Needs to work also for relative URLs
- If redirection is being used to create short links and these are used in posts/pages, they’re all gonna get replaced and you’ll lose tracking (if that’s how you’re using Redirection)
- Probably many more. As I said, this is a dirty snippet.
- You must be logged in to reply to this topic.