web-dev-qa-db-fra.com

Vérifiez si le premier paragraphe est une image, puis affichez le code personnalisé juste après?

Je voudrais ajouter du code dans functions.php qui fait ceci:

  • Si le premier paragraphe contient une image, affichez mon code personnalisé juste après. Par exemple:

    <div class="entry-content">
        <p><img src="http://example.com/example.jpg" alt="Image in 1st para" /></p>
        <div>MY CUSTOM CODE</div>
    </div>
    
  • Mais si le premier paragraphe est du texte (c’est-à-dire PAS une image), affichez mon code personnalisé juste AVANT.

    <div class="entry-content">
        <div>MY CUSTOM CODE</div>
        <p>This 1st paragraph contains text, not an image.</p>
    </div>
    

Comment fait-on ça? Un exemple d'extrait de code est le bienvenu.

PS: Le code personnalisé pourrait également être une annonce (par exemple, Google Adsense).

5
its_me

Que diriez-vous de quelques lignes simples avec jQuery?

jQuery(document).ready( function ($) {
    if ($(".entry-content:first-child").has('img').length) //this check for the img tag
        $(".entry-content:first-child").after("<div>MY CUSTOM CODE</div>");
    else
        $(".entry-content:first-child").before("<div>MY CUSTOM CODE</div>");
});

Mise à jour:

Voici une solution simple utilisant le langage natif de php DOMDocument

add_filter('the_content','add_code_before_afterImage');

function add_code_before_afterImage($content){
    $MYCODE = '<div>this is my custom code</div>';
    $doc = new DOMDocument();
    @$doc->loadHTML('<?xml encoding="'.get_bloginfo('charset').'">'.$content);
    $ps = $doc->getElementsByTagName('p');
    foreach ($ps as $p) {
        if (false !== stripos($p->nodeValue,'img'));
            return str_replace($p->nodValue, $p->nodValue.$MYCODE, $content);
        }
        break;
    }
    //if we got here then there is no img tag in the first paragraph
    //so we return the code before the content.
    return $MYCODE.$content;
}

Mise à jour 2:

Le commentaire de @ Sarathi me fait penser que vous n'avez pas réellement besoin d'analyser une partie du contenu, tirez simplement le premier paragraphe et vérifiez s'il comporte une balise img. Voici donc une solution plus simple et bien plus rapide utilisant uniquement les codes str_replace et stripos de PHP.

add_filter('the_content','simple_img_tag_search');
function simple_img_tag_search($content){

    $MYCODE = '<div>this is my custom code</div>';

    //split content to first paragraph and the rest
    $paragraphs = explode( '</p>', $content, 2 );

    //extract the first paragraph
    $first_paragraph = $paragraphs[0];

    //then just look for img tag
    if (false === stripos($first_paragraph, "<img")){
        //not found then just return the code before the content
        return $MYCODE.$content;
    }else{
        // img tag found so we return the code after the first paragraph
        return str_replace($first_paragraph.'</p>',$first_paragraph.'</p>'.$MYCODE,$content);
    }
}
6
Bainternet

Pour attraper le premier paragraphe (<p>), vous pouvez utiliser une expression rationnelle. C'est pas optimal , alors soyez prévenus. :)

Ensuite, vous testez la correspondance pour une image et insérez le contenu supplémentaire en fonction du résultat du test. J'utilise deux fonctions ici, une pour chaque étape: la première trouve le premier paragraphe, la seconde modifie la première correspondance.

// Late priority parameter to let shortcodes and other filters do their work first.
add_filter( 'the_content', 'wpse_52662_add_extra', 1000 );

/**
 * Reads the content and calls a callback to add extra content.
 *
 * @param  string $content
 * @return string
 */
function wpse_52662_add_extra( $content )
{
    // restrict to single posts:
    if ( ! is_single() )
    {
        return $content;
    }

    return preg_replace_callback(
        '~<p(>|\s+[^>]*>)(.*?)</p>~miU' // find <p>
    ,   'wpse_52662_callback'           // pass the result to the callback
    ,   $content
    ,   1                               // stop after first match
    );
}

/**
 * Callback for wpse_52662_add_extra()
 *
 * @param array $m Matches. $m[0] contains the whole match,
 *                          $m[2] the content of the paragraph.
 * @return string
 */
function wpse_52662_callback( $m )
{
    $extra = '<p><b>Hello World!</b></p>';
    return ( FALSE === strpos( $m[2], '<img' ) ) ? $extra.$m[0] : $m[0].$extra;
}
4
fuxia

Vous pouvez utiliser DOMDocument pour analyser le contenu HTML comme suit:

add_filter( 'the_content', 'add_html_after_first_image' );
function add_html_after_first_image( $content ) {

    $my_custom_html = '<div>MY CUSTOM CODE</div>';

    // Create a dom document from the post content.
    // The content needs to be wrapped in a root element to be valid xml, hence the div tags.
    // I used loadXML because loadHTML adds the unnecessary <DOCTYPE>, <html>, and <body>.
    if( $dom = DOMDocument :: loadXML( '<div>' . $content . '</div>' ) ) {

        // Create a document fragment with your custom html.
        $custom = $dom -> createDocumentFragment();
        $custom -> appendXML( $my_custom_html );

        // Get the root element, and first child.
        $root   = $dom  -> firstChild;
        $first  = $root -> firstChild;

        // Check if the first child is a paragraph, the first grandchild is an image,
        // and if the paragraph has no content other than the image.
        $has_image = 'p'   == $first -> tagName
                &&   ''    == trim( $first -> textContent )
                &&   1     == count( $first -> childNodes )
                &&   'img' == $first -> firstChild -> tagName;

        // If $has_image is true then add the custom div after the first paragraph,
        // otherwise add it before.
        $root -> insertBefore( $custom, $has_image ? $first -> nextSibling : $first );

        // Set the new content to the altered html.
        $content = $dom -> saveHTML();
    }

    return $content;
}


MODIFIER:

Voici une fonction mise à jour qui a été optimisée pour fonctionner plus rapidement que la fonction ci-dessus.

Conseil: La balise <p> ne doit contenir aucun contenu autre que la balise <img />. (Cela inclut les espaces)

add_filter( 'the_content', 'add_html_after_first_image' );
function add_html_after_first_image( $content ) {

    $my_custom_html = '<div>MY CUSTOM CODE</div>';

    // Explode the content to extract and parse only the first paragraph.
    $parts = explode( '</p>', $content, 2 );
    $p = $parts[0] . '</p>';

    // Create a dom document from the first paragraph of content.
    // I used loadXML because loadHTML adds the unnecessary <DOCTYPE>, <html>, and <body>.
    // Checking for an opening <p> tag prevents the creation of a DOMDocument,
    // and lowers the execution time on posts that don't start with a paragraph.
    if( substr( $p, 0, 3 ) == '<p>' && $dom = @DOMDocument :: loadXML( $p ) ) {

        // Create a document fragment with your custom html.
        $custom = $dom -> createDocumentFragment();
        $custom -> appendXML( $my_custom_html );

        $first  = $dom -> firstChild;

        // Check if the first child is a paragraph, the first grandchild is an image,
        // and if the paragraph has no content other than the image.
        $has_image = 'p'   == $first -> tagName
                &&   ''    == $first -> textContent
                &&    1    == count( $first -> childNodes )
                &&   'img' == $first -> firstChild -> tagName;

        // If $has_image is true then add the custom div after the first paragraph,
        // otherwise add it before.
        $dom -> insertBefore( $custom, $has_image ? $first -> nextSibling : $first );

        // Set the new content to the altered html.
        $p = $dom -> saveHTML();

    }
    // If the dom document could not be created, then the first element is not a
    // paragraph and the custom code should be prepended to the content.
    else $p = $my_custom_html . $p;

    // Append the rest of the content to the paragraph.
    return $p . $parts[1];
}
1
Sarathi Hansen