• 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.
    • This topic was modified 2 weeks, 3 days ago by James Revillini. Reason: providing implementation notes and some more detail on flaws
Viewing 2 replies - 1 through 2 (of 2 total)
  • Thread Starter James Revillini

    (@jrevillini)

    Here’s an updated version to take stabs at.

    //////////////////////////////////////////////////////////////////////////////////
    //////////////////// ?? Schwifty-?????? Link Fixer 3000? /////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////
    //
    //
    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;
        }
    
        // Define allowed post types and specific post IDs (set to [] for all)
        $allowed_post_types = ['post']; // Modify for your use case
        $allowed_post_ids = [144]; // Set specific post IDs for testing or [] for all
    
        // Get the current post object
        global $post;
        if (!$post) {
            return $content;
        }
    
        // Check if the current post matches the post types or the allowed post ID
        if (!empty($allowed_post_types) && !in_array($post->post_type, $allowed_post_types)) {
            return $content;
        }
        if (!empty($allowed_post_ids) && !in_array($post->ID, (array) $allowed_post_ids)) {
            return $content;
        }
    
        // Extract all <a> tags from content
        if (preg_match_all('/<a\s[^>]*href=["\']([^"\']+)["\']/i', $content, $matches)) {
            $urls_to_check = array_unique($matches[1]); // Unique URLs only
    
            if (!$urls_to_check) {
                return $content; // No links to change, bail early
            }
    
    
            foreach ($urls_to_check as $old_url) {
    
                $redirects = Red_Item::get_for_url($old_url); // Returns an array of Red_Item objects
                if (empty($redirects) || ! is_array($redirects) || count($redirects) < 1 ) continue;
    
                foreach ($redirects as $redirect) {
                    $action_data = $redirect->get_action_data();
                    if ( $action_data === '' || $redirect->is_regex() ) continue; // @TODO needs to be fixed to handle regex matching
                    $new_url = esc_url( $action_data );
                    $replacements[$old_url] = $new_url;
                    break; // Use the first valid redirect and move on
                }
    
            }
    
            // Only do a replacement if we found redirects
            if (!empty($replacements)) {
                foreach ($replacements as $old => $new) {
                    $content = str_replace(
                        'href="' . $old . '"',
                        'href="' . $new . '" data-schwifty-oldhref="' . esc_attr($old) . '"', // keep old URL in data attribute cuz that's fun
                        $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:

    • Doesn’t work on regex matches yet
    • Needs to work for relative URLs (this should work now but I haven’t tested it yet)
    • May or may not work for links with parameters in them. I have no idea yet.
    • 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)
    Thread Starter James Revillini

    (@jrevillini)

    →moved to gist https://gist.github.com/jrevillini/edf08952b2edb906f38644649099b33e

    Go there for most up-to-date version ??

Viewing 2 replies - 1 through 2 (of 2 total)
  • You must be logged in to reply to this topic.