Finding the paragraphs in content

I am trying to create two functions, one that catches the first paragraph of some content, and one that catches the rest, but I have hit a bit of a conundrum.

I have this in my single.php:

Read More
<div class='the_content'>
  <?php the_content(); ?>
</div>

which produces:

<div class="the_content">
   <p>The content .....</p>
   <p>The content .....</p>
   <p>The content .....</p>
</div>

each paragraph all nicely wrapped in a <p> tag. I assumed that I could simple break the explode() the content based on the string </p>, theoretically splitting the content into paragraphs, but all the content is in the first resulting array element. I investigated, and there are no <p> tags in either the HTML edit, or indeed the database entry. Both look like:

The Content .....
The Content .....
The Content .....

Note:Line breaks present, but not <p> tags.

Where does WordPress add the <p> back in? How does it find the line breaks and how can I hook a function into that?


FYI

Here is the function that fails, based closely on the the_content() function:

function get_first_paragraph(){
    $content = $firstcontent = get_the_content();
    $content = str_replace(']]>', ']]&gt;', $content);
    $content = explode('</p>',$content);

    return $content[0];
}

Related posts

Leave a Reply

3 comments

  1. The paragraphs are done by the wpautop() function, hooked to the_content, the_excerpt() & comment_text as well as 'term_description' for taxonomies.


    The plugin linked by @javipas does an enormous effort to just add this, but it’s a good example (+1). You can (modify it a little and) take the following part out of it:

    // The init function
    function wpse24553_add_p_the_content()
    {
        add_filter( 'the_content', 'wpse24553_p_the_content' );
        add_filter( 'the_content_feed', 'wpse24553_p_the_content' );
    }
    add_action( 'init', 'wpse24553_add_p_the_content' );
    
    // The actual modification function
    function wpse24553_p_the_content( $the_content )
    {
        global $post;
    
        $content_by_p = preg_split( '/</p>/is', $the_content );
    
        $i = 0;
        // Set a var to count until the targeted <p> is met - change this to your needs
        // Set to empty '' if you want to modify every paragraph
        $targeted_p = 1;
    
        static $new_content = '';
    
        foreach ( $content_by_p as $key => $p )
        {
            $i++;
            // abort and return the modified content if we're beyond the targeted <p>
            if ( $i > $targeted_p )
                {
                $new_content .= $p;
                        continue;
                }
    
            // Remove empty space at the end of a paragraph, then remove original <p>-tag
            $p = rtrim( $p );
            $p = preg_replace( '/<p>/is', '', $p );
    
            // Wrap replacements in new <p>-tags, so it validates
            $new_content .= '<p class="paragraph-link"><a name="p-'.$key.'"></a>';
            // Prepend the graf with an anchor tag
            $new_content .= '<a ref="permalink" title="Permalink to this paragraph" href="'.get_permalink( $post->ID ).'#p-'.$key.'">#</a>;
            $new_content .= $p;
            $new_content .= '</p>';
        }
    
        // Return the new content
        return $new_content;
    }
    

    Notes:

    • The function needs to be placed in your functions.php
    • You need to alter the function and what gets added/removed/modified with a single paragraph by yourself (no use case in the Q).
    • The function currently is not tested.
  2. If I have understand you, what you want is permalinks for each paragraph? The known blogger Dave Winer wrote about this a year ago, and there’s a plugin called WinerLinks that puts a ‘#’ after each paragraph, that makes that paragraph linkable.

    I hope it works for you.

  3. Where does WordPress add the <p> back in?

    afaik, by applying the ‘the_content’ filter.

    possible examples for your functions:

    function get_first_paragraph() { 
        $text = apply_filters('the_content', get_the_content() );
        $paragraphs = explode('</p>', $text);
        $first_paragraph = array_shift($paragraphs).'</p>';
    return $first_paragraph;
    }
    

    and:

    function get_last_paragraphs() { 
        $text = apply_filters('the_content', get_the_content() );
        $paragraphs = explode('</p>', $text);
        $first_paragraph = array_shift($paragraphs).'</p>';
        $rest_paragraphs = implode('</p>', $paragraphs);
    return $rest_paragraphs; 
    }