title: PHP insert ad after X paragraphs, then every Y paragraphs if the text is long enough
body: <p>I need to insert an ad code at intervals in this way:</p>
  
  <ol>
  <li><code>$insert_every_paragraphs</code> is a variable that indicates how often a paragraph should appear in the text. 10, for example.</li>
  <li><code>$minimum_paragraph_count</code> is used to see if the text is long enough for any ads, and <strong>also</strong> the very first ad should appear after this many paragraphs (then it should repeat the intervals in #1). 4, for example.</li>
  <li>The ad codes work like this: x100, x101, x102, x103, etc. Users can set how many are eligible to be added. They render like <code>[cms_ad:x100]</code> and PHP replaces them later (that part works fine).</li>
  <li>The code should stop adding ads once it gets to the end of #3. That is, even if it has enough paragraphs to keep adding ads, it should stop if it has reached x104 (in this example).</li>
  </ol>
  
  <p>So in this example, it would work like this: after 4 paragraphs, insert x100. Then, every 10 paragraphs, insert another until x103 has been inserted. Don't insert x104, even if there are 100 paragraphs. But also, if there aren't at least 34 paragraphs, x103 would never appear.</p>
  
  <p>What I have so far is this:</p>
  
  <pre><code>$paragraph_end = '&lt;/p&gt;';
  
  $insert_every_paragraphs = 10;
  $minimum_paragraph_count = 4;
  
  $embed_prefix      = 'x';
  $start_embed_id    = 'x100';
  $start_embed_count = intval( str_replace( $embed_prefix, '', $start_embed_id ) ); // ex 100
  $end_embed_id      = 'x103';
  $end_embed_count   = intval( str_replace( $embed_prefix, '', $end_embed_id ) ); // ex 104
  
  $paragraph_positions = array();
  $last_position       = -1;
  
  while ( stripos( $content, $paragraph_end, $last_position + 1 ) !== false ) {
      // Get the position of the end of the next $paragraph_end.
      $last_position         = stripos( $content, $paragraph_end, $last_position + 1 ) + 3;
      $paragraph_positions[] = $last_position;
  }
  
  // If the total number of paragraphs is bigger than the minimum number of paragraphs
  if ( count( $paragraph_positions ) &gt;= $minimum_paragraph_count ) {
      // How many ads have been added?
      $n = $start_embed_count;
      // Store the position of the last insertion.
      $previous_position = $start_embed_count;
      $i                 = 0;
      while ( $i &lt; count( $paragraph_positions ) &amp;&amp; $n &lt;= $end_embed_count ) {
  
          if ( 0 === ( $i + 1 ) % $insert_every_paragraphs &amp;&amp; isset( $paragraph_positions[ $i ] ) ) {
              $shortcode = "\n" . '[cms_ad:' . $embed_prefix . (int) $n . ']' . "\n";
  
              $position = $paragraph_positions[ $i ] + 1;
  
              if ( $position &gt; $previous_position ) {
                  $content = substr_replace( $content, $shortcode, $paragraph_positions[ $i ] + 1, 0 );
                  // Increase the saved last position.
                  $previous_position = $position;
                  // Increment number of shortcodes added to the post.
                  $n++;
              }
              // Increase the position of later shortcodes by the length of the current shortcode.
              foreach ( $paragraph_positions as $j =&gt; $pp ) {
                  if ( $j &gt; $i ) {
                      $paragraph_positions[ $j ] = $pp + strlen( $shortcode );
                  }
              }
          }
          $i++;
      }
  }
  </code></pre>
  
  <p>I thought this was working okay when the numbers were 4 and 6 instead of 4 and 10, but the error became clear when I started adjusting the values. It currently inserts an ad every 10 paragraphs, and of course it does not insert an ad after the fourth paragraph.</p>
  
  <p>I'm not opposed to using <code>explode</code> or other methods for this, of course, but this was what got me the farthest.</p>