0

I know this question has more of a WordPress background to it, but I'm hoping it's just my lack of PHP knowledge that is the problem here.

I have a regex that looks for <a> tags such as: <a href="http://website.co.uk/post/post-title">Find Out More</a>, which are generated from content inputted by the user. Once it finds this content a foreach loop runs over the matched text and uses a WordPress function $postId = url_to_postid( $url ); to convert the URL into a PostID.

This is an example output: <a href="#171">Find Out More</a>.

This works fine as long as there is one link in each piece of matched text. However if there are two or more links, it sets every link to have the same href which is incorrect.

I'm sure this is something to do with how I've got my loop running. The code I'm using is below:

<?php
$string = get_field('sample_text_box');
$pattern = "/(?<=href=(\"|'))[^\"']+(?=(\"|'))/";
preg_match_all($pattern, $string, $matches);
$urls = $matches[0];

foreach($urls as $key => $url) {
$postId[$key] = url_to_postid( $url );
}

$newstring = preg_replace($pattern , $postId[$key] , $string);
echo $newstring;
?>

The line get_field('sample_text_box'); is an Advanced Custom Field function which "returns the value of the specified field". You can read about it here if it helps: https://www.advancedcustomfields.com/resources/get_field/

Thanks!

Ruslan Osmanov
  • 20,486
  • 7
  • 46
  • 60
kieranstartup
  • 77
  • 1
  • 10
  • Are you expecting more than one `$newstring` at the end of this code block? – WillardSolutions Nov 04 '16 at 16:48
  • 1
    Can't have an HTML regex question without **the** [quintessential answer](http://stackoverflow.com/a/1732454/2191572) – MonkeyZeus Nov 04 '16 at 16:48
  • @EatPeanutButter Basically I'm just aiming to update each of the `href` values for the links which have been added in. I'm not sure if you could achieve that by having multiple `$newstring`'s merged together into one text block once all the `href`'s have been updated. – kieranstartup Nov 04 '16 at 16:59

1 Answers1

1

The problem with your code is that you are indeed replacing the pattern with a single value of $postId[$key], where $key is the last value assigned in foreach.

You also can not pass $postId instead because preg_replace expects both pattern and replacement be of the same type - whether strings, or arrays.

However, the problem is easily solved with preg_replace_callback function:

$pattern = '/(?<=href\="|\')([^"\']+)(?="|\')/m';

$new_string = preg_replace_callback($pattern, function ($matches) {
  return isset($matches[1]) ? url_to_postid($matches[1]) : $matches[0];
}, $string);
Ruslan Osmanov
  • 20,486
  • 7
  • 46
  • 60
  • Thanks for this Ruslan! I've tried pasting it in but when I run it no text is being returned. I assume I replace my `$pattern = .....` with your one. But whereabouts do I place the `$new_string ...`? Thanks! – kieranstartup Nov 04 '16 at 17:09
  • Perfect, works straight away. Thanks for supplying that link! Much appreciated! – kieranstartup Nov 04 '16 at 17:14
  • Sorry for being a total noob, but how would I append a '#' symbol in front of the returned URL's? i.e. `` Every time I try `'#' .` it appends it in front of the `$string`. – kieranstartup Nov 04 '16 at 18:12
  • Exactly, thanks! Thats the one place I didn't try it, I apologise! – kieranstartup Nov 04 '16 at 18:26