WordPress 3.5.2 Gallery order problems

I’m in the process of completing a template refresh for a WordPress-based portfolio site for one of my clients. The site has a number of existing gallery pages that are being rendered with the standard WordPress gallery code. However, the “drag ‘n’ drop” re-ordering feature seems not to be working for these galleries, and given that there are such a large number of images in each gallery I’d like to avoid having to re-upload them.

According to some answers to similar problems posted here and here, I think the issue may be to do with whether the images are attachments or links, and it’s been suggested that one solution is to use a regular expression to produce an array containing the image ids in the correct order, like so:

Read More
$post_content = $post->post_content;
preg_match('/[gallery.*ids=.(.*).]/', $post_content, $ids);
$array_id = explode(",", $ids[1]);

(Solution provided by Slevin)

However, at this point I get stuck, as it’s beyond my abilities to integrate this into the existing WordPress gallery code. Could anybody help me do this?

An example of one of the gallery pages is here.

The WordPress Gallery code is as follows (I’ve copied this into my theme’s function.php file so as to customise it).

Many thanks!

remove_shortcode('gallery');
add_shortcode('gallery', 'theme_gallery_shortcode');

function theme_gallery_shortcode($attr) {
    $post = get_post();

    static $instance = 0;
    $instance++;

    if ( !empty( $attr['ids'] ) ) {
        // 'ids' is explicitly ordered, unless you specify otherwise.
        if ( empty( $attr['orderby'] ) )
            $attr['orderby'] = 'post__in';
        $attr['include'] = $attr['ids'];
    }

    // Allow plugins/themes to override the default gallery template.
    $output = apply_filters('post_gallery', '', $attr);
    if ( $output != '' )
        return $output;

    // We're trusting author input, so let's at least make sure it looks like a valid orderby statement
    if ( isset( $attr['orderby'] ) ) {
        $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
        if ( !$attr['orderby'] )
            unset( $attr['orderby'] );
    }

    extract(shortcode_atts(array(
        'order'      => 'ASC',
        'orderby'    => 'menu_order ID',
        'id'         => $post->ID,
        'itemtag'    => 'dl',
        'icontag'    => 'dt',
        'captiontag' => 'dd',
        'columns'    => 3,
        'size'       => 'thumbnail',
    'include'    => '',
    'exclude'    => ''
), $attr));

$id = intval($id);
if ( 'RAND' == $order )
    $orderby = 'none';

if ( !empty($include) ) {
    $_attachments = get_posts( array('include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );

    $attachments = array();
    foreach ( $_attachments as $key => $val ) {
        $attachments[$val->ID] = $_attachments[$key];
    }
} elseif ( !empty($exclude) ) {
    $attachments = get_children( array('post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
} else {
    $attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
}

if ( empty($attachments) )
    return '';

if ( is_feed() ) {
    $output = "n";
    foreach ( $attachments as $att_id => $attachment )
        $output .= wp_get_attachment_link($att_id, $size, true) . "n";
    return $output;
}

$itemtag = tag_escape($itemtag);
$captiontag = tag_escape($captiontag);
$icontag = tag_escape($icontag);
$valid_tags = wp_kses_allowed_html( 'post' );
if ( ! isset( $valid_tags[ $itemtag ] ) )
    $itemtag = 'dl';
if ( ! isset( $valid_tags[ $captiontag ] ) )
    $captiontag = 'dd';
if ( ! isset( $valid_tags[ $icontag ] ) )
    $icontag = 'dt';

$columns = intval($columns);
$itemwidth = $columns > 0 ? floor(100/$columns) : 100;
$float = is_rtl() ? 'right' : 'left';

$selector = "gallery-{$instance}";

$gallery_style = $gallery_div = '';
if ( apply_filters( 'use_default_gallery_style', true ) )
    $gallery_style = "
    <style type='text/css'>
        #{$selector} {
            margin: auto;
        }
        #{$selector} .gallery-item {
            float: {$float};
            margin-top: 10px;
            text-align: center;
            width: {$itemwidth}%;
        }
        #{$selector} img {
            border: 2px solid #cfcfcf;
        }
        #{$selector} .gallery-caption {
            margin-left: 0;
        }
    </style>
    <!-- see gallery_shortcode() in wp-includes/media.php -->";
$size_class = sanitize_html_class( $size );
$gallery_div = "<div id='$selector' class='gallery galleryid-{$id} gallery-columns-{$columns} gallery-size-{$size_class}'>";
$output = apply_filters( 'gallery_style', $gallery_style . "ntt" . $gallery_div );

$i = 0;
foreach ( $attachments as $id => $attachment ) {
    $link = isset($attr['link']) && 'file' == $attr['link'] ? wp_get_attachment_link($id, $size, false, false) : wp_get_attachment_link($id, $size, true, false);

    $output .= "<{$itemtag} class='gallery-item'>";
    $output .= "
        <{$icontag} class='gallery-icon'>
            $link
        </{$icontag}>";
    if ( $captiontag && trim($attachment->post_excerpt) ) {
        $output .= "
            <{$captiontag} class='wp-caption-text gallery-caption'>
            " . wptexturize($attachment->post_excerpt) . "
            </{$captiontag}>";
    }
    $output .= "</{$itemtag}>";
    if ( $columns > 0 && ++$i % $columns == 0 )
        $output .= '<br style="clear: both" />';
}

$output .= "
        <br style='clear: both;' />
    </div>n";

return $output;
}

Related posts

Leave a Reply

1 comment

  1. This has thrown a bunch of people for a loop, and even the links you posted don’t work for a page with more than one gallery (as far as I can tell while trying to implement). Here’s what I found worked for my implementation of a custom gallery:

    Change your code to the following (“post__in”, “$galleries”, and “$ids” being the important changes):

    extract(shortcode_atts(array(
        'order'      => 'DESC',
        'orderby'    => 'post__in',
        'id'         => $post->ID,
        'itemtag'    => 'dl',
        'icontag'    => 'dt',
        'captiontag' => 'dd',
        'columns'    => 3,
        'size'       => 'thumbnail',
        'include'    => '',
        'exclude'    => '',
        'ids'        => ''
    ), $attr));
    
    $galleries=grab_ids_from_gallery();
    $ids=$galleries[$instance-1];
    
    $id = intval($id);
    if ( 'RAND' == $order )
        $orderby = 'none';
    
    if ( !empty($ids) ) {
    
        $ids = preg_replace( '/[^0-9,]+/', '', $ids );
        $attachments = get_posts( array('include' => $ids, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    
    } elseif ( !empty($exclude) ) {
        $exclude = preg_replace( '/[^0-9,]+/', '', $exclude );
        $attachments = get_children( array('post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    } else {
        $attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    }
    

    Then include the following helper function:

    function grab_ids_from_gallery() {
    
        global $post;
        $attachment_ids = array();
        $pattern = get_shortcode_regex();
        $galleries=array();
    
    
        if (preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches ) ) {   //finds the     "gallery" shortcode and puts the image ids in an associative array at $matches[3]
            $count=count($matches[3]);      //in case there is more than one gallery in the post.
            for ($i = 0; $i < $count; $i++){
                $ids = array();
                $atts = shortcode_parse_atts( $matches[3][$i] );
                if ( isset( $atts[ids] ) ){
                    $attachment_ids = explode( ',', $atts[ids] );
                    $ids = array_merge($ids, $attachment_ids);
                }
                $galleries[$i]=$ids;
            }
        }
        return $galleries;
    
    }
    add_action( 'wp', 'grab_ids_from_gallery' );
    

    This may not be the very best way to go about this, but it’s working for me.