Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Place content in between paragraphs without images

Tags:

html

php

I am using the following code to place some ad code inside my content .

<?php
$content = apply_filters('the_content', $post->post_content);
$content = explode (' ', $content);
$halfway_mark = ceil(count($content) / 2);
$first_half_content = implode(' ', array_slice($content, 0, $halfway_mark));
$second_half_content = implode(' ', array_slice($content, $halfway_mark));
echo $first_half_content.'...';
echo ' YOUR ADS CODE';
echo $second_half_content;
?>

How can i modify this so that the 2 paragraphs (top and bottom) enclosing the ad code should not be the one having images. If the top or bottom paragraph has image then try for next 2 paragraphs.

Example: Correct Implementation on the right.

enter image description here

like image 555
Debajyoti Das Avatar asked Feb 28 '14 09:02

Debajyoti Das


2 Answers

preg_replace version

This code steps through every paragraph ignoring those that contain image tags. The $pcount variable is incremented for every paragraph found without an image, if an image is encountered however, $pcount is reset to zero. Once $pcount reaches the point where it would hit two, the advert markup is inserted just before that paragraph. This should leave the advert markup between two safe paragraphs. The advert markup variable is then nullified so only one advert is inserted.

The following code is just for set up and could be modified to split the content differently, you could also modify the regular expression that is used — just in case you are using double BRs or something else to delimit 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 bulk of the code that runs the replacement. This could be modified to insert more than one advert, or to support more involved image checking.

$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 this code has been executed the $content variable will contain the enhanced HTML.


PHP versions prior to 5.3

As your chosen testing area does not support PHP 5.3, and so does not support anonymous functions, you need to use a slightly modified and less succinct version; that makes use of a named function instead.

Also, in order to support content that may not actually leave space for the advert in it's second half I have modified the $mpoint so that it is calculated to be 80% from the end. This will have the effect of including more in the $second part — but will also mean your adverts will be generally placed higher up in the mark-up. This code has not had any fallback implemented into it, because your question does not mention what should happen in the event of 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);
like image 130
Pebbl Avatar answered Nov 14 '22 19:11

Pebbl


You could try this:

    <?php
  $ad_code = 'SOME SCRIPT HERE';

  // Your code.
  $content = apply_filters('the_content', $post->post_content);

  // Split the content at the <p> tags.
  $content = explode ('<p>', $content);

  // Find the mid of the article.
  $content_length = count($content);
  $content_mid = floor($content_length / 2);

  // Save no image p's index.
  $last_no_image_p_index = NULL;

  // Loop beginning from the mid of the article to search for images.
  for ($i = $content_mid; $i < $content_length; $i++) {
    // If we do not find an image, let it go down.
    if (stripos($content[$i], '<img') === FALSE) {
      // In case we already have a last no image p, we check 
      // if it was the one right before this one, so we have
      // two p tags with no images in there.
      if ($last_no_image_p_index === ($i - 1)) {
        // We break here.
        break;
      }
      else {
        $last_no_image_p_index = $i;
      }
    }
  }

  // If no none image p tag was found, we use the last one.
  if (is_null($last_no_image_p_index)) {
    $last_no_image_p_index = ($content_length - 1);
  }

  // Add ad code here with trailing <p>, so the implode later will work correctly.
  $content = array_slice($content, $last_no_image_p_index, 0, $ad_code . '</p>');

  $content = implode('<p>', $content);
?>

It will try to find a place for the ad from the mid of your article and if none is found the ad is put to the end.

Regards func0der

like image 40
func0der Avatar answered Nov 14 '22 20:11

func0der