Parsing WordPress post content

2020-03-06 03:33发布

问题:

I've got a weird layout to get around and am at a loss, even in the planning stage. Essentially I need to separate out all content that's not a .gallery and put it into an <aside />. I initially considered a plugin using the edit_post hook from the Plugin API, but have since decided against it because this content change is layout specific and I want to maintain a clean database. So...

How can I parse through WP's the_content for content that's not .gallery? Admittedly not a PHP guy, so I doubly appreciate the help!


As per Michael's comment below - here's an example of WP's the_content class output:

HTML

<div class="entry-content">
    <div class="gallery">
        <dl class="gallery-item">
            <dt class="gallery-icon portrait">
                <img src="/imagePath/etc.jpg" class="attachment-thumbnail">
            </dt>
        </dl>
        <dl class="gallery-item">
            <dt class="gallery-icon portrait">
                <img src="/imagePath/etc.jpg" class="attachment-thumbnail">
            </dt>
        </dl>
        <dl class="gallery-item">
            <dt class="gallery-icon portrait">
                <img src="/imagePath/etc.jpg" class="attachment-thumbnail">
            </dt>
        </dl>
    </div>
    <p>Curabitur vulputate, ligula lacinia scelerisque tempor, lacus lacus ornare ante, ac egestas est urna sit amet arcu. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed molestie augue sit amet.</p>
    <ul>
        <li>Item A</li>
        <li>Item B</li>
        <li>Item C</li>
    </ul>
</div>

Desired Output

<div class="entry-content">
    <div class="gallery">
        <dl class="gallery-item">
            <dt class="gallery-icon portrait">
                <img src="/imagePath/etc.jpg" class="attachment-thumbnail">
            </dt>
        </dl>
        <dl class="gallery-item">
            <dt class="gallery-icon portrait">
                <img src="/imagePath/etc.jpg" class="attachment-thumbnail">
            </dt>
        </dl>
        <dl class="gallery-item">
            <dt class="gallery-icon portrait">
                <img src="/imagePath/etc.jpg" class="attachment-thumbnail">
            </dt>
        </dl>
    </div>
    <aside>
        <p>Curabitur vulputate, ligula lacinia scelerisque tempor, lacus lacus ornare ante, ac egestas est urna sit amet arcu. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed molestie augue sit amet.</p>
        <ul>
            <li>Item A</li>
            <li>Item B</li>
            <li>Item C</li>
        </ul>
    </aside>
</div>

回答1:

You'll want to use a Dom Parser for this. Here's an example in how you can go about it using your markup as an example. Testing yielded the desired results, so hopefully this will give you the head start you need:

add_filter( 'the_content', 'wrap_nongallery_aside', 20 );
function wrap_nongallery_aside($content){
    $dom = new DOMDocument();
    $dom->loadHTML($content);
    $aside = $dom->createElement('aside');
    $xpath = new DOMXPath($dom);
    $not_gallery = $xpath->query('//div[@class="entry-content"]/*[not(contains(@class, "gallery"))]');

    foreach($not_gallery as $ng){
        $aside->appendChild($ng);
    }
    $dom->getElementsByTagName('div')->item(0)->appendChild($aside);
    return $dom->saveHTML();
}


回答2:

Maiorano84's answer worked beautifully, but prior to his reply I worked out an alternate method that's less specific to my situation, so I figured it'd be good to share.

I had originally written off the plugin approach because it requires changing post content itself - not just the format of the output, but realized that plugins live independent of the theme installation. Below is a very simple, developer targeted plugin that converts a [aside /] shortcodes into HTML elements. It's entirely based on BSD Aside by Sean D Burkin. I'll eventually include a button for the WP text editor and open source it.

<?php
/*
Plugin Name: RW Content Aside
Description: Inserts aside formatting into post content via shortcodes
Author: Daniel Redwood
Version: 0.1
Author URI: http://www.rdwd.fm/

Based on SBD Aside by Sean B. Durkin:
Original Plugin: http://seanbdurkin.id.au/pascaliburnus2/archives/51
Author: http://www.seanbdurkin.id.au
*/

if ( !is_admin() ){
  add_filter('the_content', 'handle_rw_aside');
}

function generate_random_str( $length=10)
{
  return substr(md5(rand()), 0, $length);
}

function generate_place_marker()
{
  return '@' . generate_random_str( 10) . '@';
}

function GetBody( $aside_instruction) {
  return preg_replace( '~^((<p>)?  \S+\s*=\s*.*?(<br \/>|<\/p>)\n?)*~mi', '', $aside_instruction);
}

function handle_rw_aside($the_content)
{
  $begin = generate_place_marker();
  $end   = generate_place_marker();

  $new_content = preg_replace(
    '~^((<p>)?\[aside\](<br />|</p>))(.*?)(^(<p>)?\[\/aside\](<br />|</p>))~ms',
    $begin . '$4' . $end,
    $the_content);

  $new_content = preg_replace_callback(
    '~^(<p>)?(!+\[\/?aside\])~m',
    function ($match) {
      return $match[1] . substr( $match[2], 1);
      },
    $new_content);

  $pattern = '~'.$begin.'(.*?)'.$end.'~s';

  return preg_replace_callback(
    $pattern,
    function ($match) {
      $aside_instruction = $match[1];
      $body = GetBody( $aside_instruction);
      $aside = '<aside class="contentAside">' . $body . '</aside>';
      return $aside;
      },
    $new_content);

}

?>