• I am using this preg_replace code to change all imgur links on my site:

    add_filter('wp_insert_post_data', 'pm_add_memegen');
    function pm_add_memegen( $data ) {
       $data['post_content'] = preg_replace('/imgur.com\/(?!memegen\/create)/', 'imgur.com/memegen/create/', $data['post_content']);
       return $data;
    }

    But this also affects a Shortcode I have to use to display Imgur ablums which I do not want, because the shortcode will break.

    [wpws url="https://imgur.com/a/zaNdd/all" query=".posts"]

    Is there a way I can force the preg_replace code to ignore the shortcode and only affect the images displayed on my site?

    Thanks

Viewing 9 replies - 1 through 9 (of 9 total)
  • Moderator bcworkz

    (@bcworkz)

    Replace this regexp '/imgur.com\/(?!memegen\/create)/'
    with this one:
    '/(?<!\[wpws\surl="http:\/\/)imgur.com\/(?!memegen\/create)/'

    Thread Starter poopymonster

    (@poopymonster)

    The shortcode still gets converted to

    [wpws url="https://i.imgur.com/memegen/create/a/zaNdd/all" query=".posts"]

    This is what the code looks like after your proposed edit:

    add_filter('wp_insert_post_data', 'pm_add_memegen');
    function pm_add_memegen( $data ) {
       $data['post_content'] = preg_replace('/(?<!\[wpws\surl="http:\/\/)imgur.com\/(?!memegen\/create)/', 'imgur.com/memegen/create/', $data['post_content']);
       return $data;
    }

    Thanks for the suggestion though ??

    Moderator bcworkz

    (@bcworkz)

    https://i.imgur
    Where did the i sub-domain come from? Is that part of the original URL? If so, any idea what the possible range of sub-domains might be – as in longest possible characters in the sub-domain. I think sub-domains could be accommodated in the regexp with a slight adjustment.

    I’m fairly sure shortcodes without imgur subdomains do not get converted, am I right?

    Thread Starter poopymonster

    (@poopymonster)

    What the i does I’m not entirely sure. You can remove or add it to any of their addresses and every page still loads like they would otherwise.

    eg:
    https://imgur.com/a/s9CIv/all
    https://i.imgur.com/a/s9CIv/all

    https://i.imgur.com/yNf67Rt.png
    https://imgur.com/yNf67Rt.png

    Both instances get converted.

    [wpws url=”https://i.imgur.com/a/zaNdd/all&#8221; query=”.posts”]
    Becomes
    [wpws url=”https://i.imgur.com/memegen/create/a/zaNdd/all&#8221; query=”.posts”]

    [wpws url=”https://imgur.com/a/zaNdd/all&#8221; query=”.posts”]
    Becomes
    [wpws url=”https://imgur.com/memegen/create/a/zaNdd/all&#8221; query=”.posts”]

    Moderator bcworkz

    (@bcworkz)

    Hmmm, that’s disappointing. The regexp worked correctly on my installation. I wonder if it has to do with how you implemented my original code by using a plugin. You misunderstood where to place my code in our previous thread, I meant your theme’s functions.php, not wp-includes/functions.php.

    Since the plugin approach was working for you I let it go, but now I wonder if the plugin is not accepting the negative look behind code that should have prevented changes to shortcode URLs. Try placing the code on your theme’s functions.php and deactivating the code plugin. Be advised that when you alter a theme’s code, the changes could be lost when the theme updates. A couple ways around this is to create a child theme or a simple plugin to contain the code.

    Thread Starter poopymonster

    (@poopymonster)

    I have no idea what’s going wrong on my end.

    I removed the code from the plugin and added the code to my themes functions.php and the shortcode still gets converted.

    Moderator bcworkz

    (@bcworkz)

    It could be differences in PHP versions or installed modules. I’ve been led to believe the negative look behind syntax I used is not universally supported. So it’s not that there’s anything wrong on your end, it’s just different. That leaves us with how to exclude shortcodes without negative look behind.

    I don’t see a way with a single regexp. One possible approach would be to use other PHP string functions to break up the post content into shortcode and non-shortcode pieces and only apply the preg_replace to the non-shortcode pieces. Then reassemble the pieces back together again.

    A couple passes with explode() should do it, first on ‘[wpws’, then on ‘]’. However, dealing with edge conditions where the shortcode is the very first or very last element complicates things, as well as the possible occurrence of ‘]’ that is not related to a shortcode. I’m not able to offer functional code for this, but at least you know there is a way to deal with this issue. It’s not hopeless.

    Thread Starter poopymonster

    (@poopymonster)

    Very insightful. Thanks again for your detailed help.

    Moderator bcworkz

    (@bcworkz)

    I just learned something new to me last night that could be useful in your situation. I suggested 2 passes because I didn’t think there was a way to capture the delimiter if it were the entire shortcode. As it turns out there is a way with preg_split() by using the PREG_SPLIT_DELIM_CAPTURE flag.
    https://php.net/manual/en/function.preg-split.php

    By splitting the content with preg_split('/(\[wpws.*?])/', $content, -1, PREG_SPLIT_DELIM_CAPTURE ), you should get an array of alternating content segments and shortcodes. By only applying our initial preg_replace() to segments that do not start with ‘[wpws’, then once the segments are re-assembled into a single content value, you should have the results you seek.

Viewing 9 replies - 1 through 9 (of 9 total)
  • The topic ‘Preg_replace can it ignore shortcodes?’ is closed to new replies.