Search code examples
regexwordpresspreg-replacepreg-replace-callback

Assistance needed with a regular expression


I have a block of content with people's names in double brackets. For example:

Lorem ipsum dolor sit amet, consectetur [[Jane Doe]] adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco [[John Doe]] laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, [[Susan Van-Something]] sunt in culpa qui officia deserunt mollit anim id est laborum.

I am trying to write a regular expression that takes the names out of the double brackets and replaces them in the content with a link following the formatting below:

<a href='http://www.example.com/jane-doe/'>Jane Doe</a>

In the URL the spaces are transformed into hyphens and the entire name is lowercased.

So far i have

// the filter function
function names_brackets( $content ) {
    // regex replace the names with links
    // return the content
    return preg_replace_callback( "/^([[[A-Za-z0-9- ]+?]])/" , "names_callback" , $content);
}

// callback function to allow post processing
function names_callback ( $matches ) {
    $find = array(' ', '[', ']');
    $replace = array('-', '', '');
    return '<a href="http://www.example.com/' . strtolower( str_replace($find, $replace, $matches[1]) ) . '">' . str_replace(']', '', str_replace('[', '', $matches[1])) . '</a>';
}

Unfortunately I suspect that there is something wrong with the regular expression. Any help would be appreciated.


Solution

  • You do need to escape your brackets in the pattern, but there's still room for improvement: you actually don't have to do another search-and-replace within the callback function, if you use several capture groups. Like here:

    function names_brackets( $content ) {
        return preg_replace_callback('/(\[\[)([\w -]+?)(]])/',
                   'names_callback', $content);
    }
    
    function names_callback ( $matches ) {
        return '<a href="http://www.example.com/' 
               . strtolower(str_replace(' ', '-', $matches[2])) 
               . "\">$matches[2]</a>";
    }
    

    This way both opening and closing brackets will still be cut out from the result, but the callback function won't even have to know about them: it only uses the second group - the one with the name.