22

Is there a way to split up the post content and the gallery short code. I want to display the gallery outside my normal content no matter how or where it is placed. I can use this to get the shortcode itself:

if(has_shortcode(get_the_content(), 'gallery')){
    $pattern = get_shortcode_regex(); 
    preg_match("/$pattern/s", get_the_content(), $matches);
    echo do_shortcode($matches[0]);
}

But this doesn't work if the gallery short code isn't the first instance. Is there a way to split my content and gallery up completely?


Edit: I have a semi-solution but it seems like a long winded way to go about it. It first grabs the first shortcode in the post (which needs to be fixed since I only want the "Gallery" shortcode) then removes all shortcodes from the content (again, not really what I want to do.

<?php if(has_shortcode(get_the_content(), 'gallery')) : ?>
    <?php 
        $pattern = get_shortcode_regex(); 
        preg_match("/$pattern/s", get_the_content(), $matches);
    ?>
    <div id="content">
        <?php echo strip_shortcodes(get_the_content()); ?>
    </div>
    <div id="gallery">
        <?php echo do_shortcode($matches[0]); ?>
    </div>
<?php endif; ?>

Edit #2 - Ok, I've been able to only get gallery shortcodes in the post. I've also added a filter to remove the gallery shortcode form the_content() - the problem is that its not necessarily removing the shortcode since it does post it, but its not allowing me to run "do_shortcode()"

Functions.php

function remove_gallery($content) {
    global $post;

    if($post->post_type == 'artcpt')
        remove_shortcode('gallery', $content);

    return $content;
}
add_filter( 'the_content', 'remove_gallery', 6); 

The Loop

<?php preg_match('/\[gallery ids=[^\]]+\]/', get_the_content(), $matches); ?>
<div id="content">
    <?php the_content(); ?>
</div>
<div id="gallery">
    <?php echo do_shortcode($matches[0]); ?>
</div>

in The Loop it will return my short code Twice (i'm on a single page, should be looped twice - so its not running do_shortcode()). Not sure why.

  • 1
    Have you considered adding a separate WYSYWIG meta box just for the gallery? You could then always call for that after the_content(). Trickier if there are already many pages like this, however. – GhostToast Nov 6 '13 at 21:29
  • I agree that is a possibility, but I was trying to avoid the need of another big editor - trying to make it as simple and straight forward as possible. I wish I could (without a plugin of course) just have an add gallery metabox or something similar. – Howdy_McGee Nov 6 '13 at 21:41
  • Why don’t you use the solution from Using preg_replace to separate gallery from the_content? – fuxia Apr 6 '14 at 17:12
24

Open to anybody who can simplify this but here's what I came up with that worked for me.

First thing's first - get the gallery, using get_post_gallery(), as soon as the loop starts:

<?php if( have_posts() ) : ?>

    <?php while( have_posts() ) :
            the_post();
            $gallery = get_post_gallery();
            $content = strip_shortcode_gallery( get_the_content() );
    ?>

        <div id="content">
            <?php echo $content; ?>
        </div> <!-- id="content" -->

        <div id="gallery">
            <?php echo $gallery; ?>
        </div> <!-- id="gallery" -->

    <?php endwhile; ?>

<?php endif; ?>

strip_shortcode_gallery() Function - functions.php

function strip_shortcode_gallery( $content ) {
    preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches, PREG_SET_ORDER );

    if ( ! empty( $matches ) ) {
        foreach ( $matches as $shortcode ) {
            if ( 'gallery' === $shortcode[2] ) {
                $pos = strpos( $content, $shortcode[0] );
                if( false !== $pos ) {
                    return substr_replace( $content, '', $pos, strlen( $shortcode[0] ) );
                }
            }
        }
    }

    return $content;
}

Resources:

Stackoverflow:

What I was originally going off of, which didn't work as expected:

4

Core shortcode Regular Expressions

Basically we can do that with a Regex - actually even with the Regex provided by core by get_shortcode_regex().

First we need to grab the shortcode tags and build a regex. The core function get_shortcode_regex() sadly offers no chance to throw in an argument so we'd be left with a regex that matches each and every shortcode, which is undesired as we only want to target the [gallery] shortcode.

// Get all tags as Array
$tags = $GLOBALS['shortcode_tags'];
// remove the gallery-shortcode; 'gallery' is the key
unset( $tags['gallery'] );
// retrieve all shortcodes (but not 'gallery') separated by a vertical pipe char/the "or" Regex char
$tags = join( '|', array_map(
    'preg_quote',
    array_keys( $GLOBALS['shortcode_tags'] )
) );

Catch all galleries

Next we need a Regex that catches all galleries. Therefore we are calling preg_match_all() as it will return all Matches for the gallery shortcode as array with an 0 index (the rest will be partial matches and can be ignored).

$pattern = get_shortcode_regex();
preg_match_all( "/$pattern/s", get_the_content(), $galleries );

Now $galleries[0] holds an array of gallery shortcode tags.

The content without galleries

The next thing is that we need to do is to remove all [gallery] shortcodes from the content. We will use the same Regex again and run it on get_the_content(). Of course we apply the the_content filter as shortcode could have been added through a callback at render time.

$content = preg_replace_callback(
    "/$pattern/s",
    'strip_shortcode_tag',
    apply_filters( 'the_content', get_the_content() )
);

The $content variable now holds our content.

Example callback to alter the content

or: How you can split up the content into galleries and the rest of the post

We could easily just replace the content with our new content during a callback:

$tags = $GLOBALS['shortcode_tags'];
unset( $tags['gallery'] );

$tags = join( '|', array_map(
    'preg_quote',
    array_keys( $GLOBALS['shortcode_tags'] )
) );
$pattern = get_shortcode_regex();

preg_match_all( "/{$pattern}/s", get_the_content(), $galleries );

echo $galleries;
echo "<hr>";
echo preg_replace_callback(
    "/{$pattern}/s",
    'strip_shortcode_tag',
    apply_filters( 'the_content', get_the_content() )
);

which would first add all galleries, then add our content without galleries, both separated by a horizontal rule. This is just a starting point.

2

It should not be sooo complicated. The code below can be shortened down to a couple of lines at wish.

Approach 1. Get the clean post content by removing all shortcodes, including the gallery one from the post content.

NB: all the other shortcodes will be removed from the post. If you do not place custom shortcodes there, then the approach is for you.

Assume you are in the WP loop

$ctt = apply_filters('the_content',strip_shortcodes(get_the_content())); // This is your cleaned content
$glry = get_post_gallery(); // and here is the gallery.

Assume you are out

$my_postid = 12;
$my_post = get_post($my_postid);
$ctt = apply_filters('the_content',strip_shortcodes($my_post->post_content));
$glry = get_post_gallery($my_postid);

Approach 2. Remove only [gallery] shortcode, keep all other shortcodes in.

Relies on the internal realisation of the how the [gallery] shortcode looks like, which can be changed by WP team, so maybe not as future proof as the 1st approach:

In the WP loop

$ctt = preg_replace('/\[gallery.*\]/', '', get_the_content());
$ctt = apply_filters('the_content',$ctt); // This is your cleaned content
$glry = get_post_gallery();

Out of it

$my_postid = 12;
$my_post = get_post($my_postid);
$ctt = apply_filters('the_content',preg_replace('/\[gallery.*\]/', '', $my_post->post_content));
$glry = get_post_gallery($my_postid);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.