preg_replace version
This code goes through each paragraph, ignoring those that contain image tags. The $pcount incremented for each paragraph found without an image, if the image occurs, however, $pcount is reset to zero. As soon as $pcount reaches the point where it reaches two, advertising markup will be inserted immediately before this paragraph. This should leave the markup between two safe paragraphs. Then, the ad layout variable is canceled, so only one ad is inserted.
The following code is for customization purposes only and can be changed to separate the content differently, you can also change the regular expression that is used - just in case you use double BRs or something else to separate your paragraphs.
/// set our advert content $advert = '<marquee>BUY THIS STUFF!!</marquee>' . "\n\n"; /// calculate mid point $mpoint = floor(strlen($content) / 2); /// modify back to the start of a paragraph $mpoint = strripos($content, '<p', -$mpoint); /// split html so we only work on second half $first = substr($content, 0, $mpoint); $second = substr($content, $mpoint); $pcount = 0; $regexp = '/<p>.+?<\/p>/si';
The rest is the main part of the code that triggers the replacement. This can be modified to insert more than one ad or to support more thorough image verification.
$content = $first . preg_replace_callback($regexp, function($matches){ global $pcount, $advert; if ( !$advert ) { $return = $matches[0]; } else if ( stripos($matches[0], '<img ') !== FALSE ) { $return = $matches[0]; $pcount = 0; } else if ( $pcount === 1 ) { $return = $advert . $matches[0]; $advert = ''; } else { $return = $matches[0]; $pcount++; } return $return; }, $second);
After executing this code, the $content variable will contain rich HTML.
PHP versions up to 5.3
Since your chosen test area does not support PHP 5.3 and therefore does not support anonymous functions, you need to use a slightly modified and less compressed version; a named function is used instead.
In addition, in order to support content that actually leaves no room for advertising in the second half, I changed $mpoint so that it was calculated at 80% of the end. This will result in the inclusion of more in the $second part - but also means that your advertisements will usually be placed higher in the premium. This code did not implement any reserve in it, because your question does not mention what should happen in the event of a failure.
$advert = '<marquee>BUY THIS STUFF!!</marquee>' . "\n\n"; $mpoint = floor(strlen($content) * 0.8); $mpoint = strripos($content, '<p', -$mpoint); $first = substr($content, 0, $mpoint); $second = substr($content, $mpoint); $pcount = 0; $regexp = '/<p>.+?<\/p>/si'; function replacement_callback($matches){ global $pcount, $advert; if ( !$advert ) { $return = $matches[0]; } else if ( stripos($matches[0], '<img ') !== FALSE ) { $return = $matches[0]; $pcount = 0; } else if ( $pcount === 1 ) { $return = $advert . $matches[0]; $advert = ''; } else { $return = $matches[0]; $pcount++; } return $return; } echo $first . preg_replace_callback($regexp, 'replacement_callback', $second);