Editing built in Gallery shortcode to filter by categories

So I’m trying to add or change the built in gallery shortcode so that it can display all images of a specific category that we’ll call internal medicine with an id of 2, but also able to have the same functionality if I wanted to grab all the images of a different category lets say called downtown with an id of 4, where can I start with this? Here’s the code for the built-in shortcode that I’m trying to edit.

    add_shortcode('gallery', 'gallery_shortcode');
/**
 * Builds the Gallery shortcode output.
 *
 * This implements the functionality of the Gallery Shortcode for displaying
 * WordPress images on a post.
 *
 * @since 2.5.0
 *
 * @staticvar int $instance
 *
 * @param array $attr {
 *     Attributes of the gallery shortcode.
 *
 *     @type string       $order      Order of the images in the gallery. Default 'ASC'. Accepts 'ASC', 'DESC'.
 *     @type string       $orderby    The field to use when ordering the images. Default 'menu_order ID'.
 *                                    Accepts any valid SQL ORDERBY statement.
 *     @type int          $id         Post ID.
 *     @type string       $itemtag    HTML tag to use for each image in the gallery.
 *                                    Default 'dl', or 'figure' when the theme registers HTML5 gallery support.
 *     @type string       $icontag    HTML tag to use for each image's icon.
 *                                    Default 'dt', or 'div' when the theme registers HTML5 gallery support.
 *     @type string       $captiontag HTML tag to use for each image's caption.
 *                                    Default 'dd', or 'figcaption' when the theme registers HTML5 gallery support.
 *     @type int          $columns    Number of columns of images to display. Default 3.
 *     @type string|array $size       Size of the images to display. Accepts any valid image size, or an array of width
 *                                    and height values in pixels (in that order). Default 'thumbnail'.
 *     @type string       $ids        A comma-separated list of IDs of attachments to display. Default empty.
 *     @type string       $include    A comma-separated list of IDs of attachments to include. Default empty.
 *     @type string       $exclude    A comma-separated list of IDs of attachments to exclude. Default empty.
 *     @type string       $link       What to link each image to. Default empty (links to the attachment page).
 *                                    Accepts 'file', 'none'.
 * }
 * @return string HTML content to display gallery.
 */
function 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'];
    }
    /**
     * Filters the default gallery shortcode output.
     *
     * If the filtered output isn't empty, it will be used instead of generating
     * the default gallery template.
     *
     * @since 2.5.0
     * @since 4.2.0 The `$instance` parameter was added.
     *
     * @see gallery_shortcode()
     *
     * @param string $output   The gallery output. Default empty.
     * @param array  $attr     Attributes of the gallery shortcode.
     * @param int    $instance Unique numeric ID of this gallery shortcode instance.
     */
    $output = apply_filters( 'post_gallery', '', $attr, $instance );
    if ( $output != '' ) {
        return $output;
    }
    $html5 = current_theme_supports( 'html5', 'gallery' );
    $atts = shortcode_atts( array(
        'order'      => 'ASC',
        'orderby'    => 'menu_order ID',
        'id'         => $post ? $post->ID : 0,
        'itemtag'    => $html5 ? 'figure'     : 'dl',
        'icontag'    => $html5 ? 'div'        : 'dt',
        'captiontag' => $html5 ? 'figcaption' : 'dd',
        'columns'    => 3,
        'size'       => 'thumbnail',
        'include'    => '',
        'exclude'    => '',
        'link'       => ''
    ), $attr, 'gallery' );
    $id = intval( $atts['id'] );
    if ( ! empty( $atts['include'] ) ) {
        $_attachments = get_posts( array( 'include' => $atts['include'], 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $atts['order'], 'orderby' => $atts['orderby'] ) );
        $attachments = array();
        foreach ( $_attachments as $key => $val ) {
            $attachments[$val->ID] = $_attachments[$key];
        }
    } elseif ( ! empty( $atts['exclude'] ) ) {
        $attachments = get_children( array( 'post_parent' => $id, 'exclude' => $atts['exclude'], 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $atts['order'], 'orderby' => $atts['orderby'] ) );
    } else {
        $attachments = get_children( array( 'post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $atts['order'], 'orderby' => $atts['orderby'] ) );
    }
    if ( empty( $attachments ) ) {
        return '';
    }
    if ( is_feed() ) {
        $output = "\n";
        foreach ( $attachments as $att_id => $attachment ) {
            $output .= wp_get_attachment_link( $att_id, $atts['size'], true ) . "\n";
        }
        return $output;
    }
    $itemtag = tag_escape( $atts['itemtag'] );
    $captiontag = tag_escape( $atts['captiontag'] );
    $icontag = tag_escape( $atts['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( $atts['columns'] );
    $itemwidth = $columns > 0 ? floor(100/$columns) : 100;
    $float = is_rtl() ? 'right' : 'left';
    $selector = "gallery-{$instance}";
    $gallery_style="";

So the goal of this would be able to put or or however way so that it displays all the images in a specific category, so any help would be very appreciated!

edit
so the way I want it to work is to be able to put and have all images or the top 20 most recent appear in the post or another example would be and what I use to make these custom post types/categories is with the plugin ToolSet Types

function 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'];
}
/**
 * Filters the default gallery shortcode output.
 *
 * If the filtered output isn't empty, it will be used instead of generating
 * the default gallery template.
 *
 * @since 2.5.0
 * @since 4.2.0 The `$instance` parameter was added.
 *
 * @see gallery_shortcode()
 *
 * @param string $output   The gallery output. Default empty.
 * @param array  $attr     Attributes of the gallery shortcode.
 * @param int    $instance Unique numeric ID of this gallery shortcode instance.
 */
$output = apply_filters( 'post_gallery', '', $attr, $instance );
if ( $output != '' ) {
    return $output;
}
$html5 = current_theme_supports( 'html5', 'gallery' );
$atts = shortcode_atts( array(
    'order'      => 'ASC',
    'orderby'    => 'menu_order ID',
    'id'         => null,
    'itemtag'    => $html5 ? 'figure'     : 'dl',
    'icontag'    => $html5 ? 'div'        : 'dt',
    'captiontag' => $html5 ? 'figcaption' : 'dd',
    'columns'    => 3,
    'size'       => 'thumbnail',
    'include'    => '',
    'exclude'    => '',
    'link'       => '',
    'category' => null,
    'post_type' => 'uc-general-gallery',
    'img' => null
), $attr, 'gallery' );
$ids = array();
ob_start();
if ($atts['id'] != null ) {
    $id_str = preg_replace('/\s+/', '', $atts['id']); // strip whitespace
    $ids = explode(',', $id_str);
    ?>
     <?php foreach($ids as $id): ?>
                <?php if(is_numeric($id)): ?>
                                    <?php endif; ?>
            <?php endforeach; ?>
            <?php
} else if($atts['category'] != null) {
    $cat_str = preg_replace('/\s+/', '', $atts['category']); // strip whitespace
    $args = array(
        'post_type'         => $atts['post_type'],
        'order'             => 'DESC',
        'category_name'     => $cat_str,
        'posts_per_page' => 999
        );
    $the_query = new WP_Query( $args );
    if($the_query->have_posts() ) :
        ?>
         <?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
         <?php endwhile; ?>
                     <?php
    endif;
}
if ( ! empty( $atts['include'] ) ) {
    $_attachments = get_posts( array( 'include' => $atts['include'], 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $atts['order'], 'orderby' => $atts['orderby'] ) );
    $attachments = array();
    foreach ( $_attachments as $key => $val ) {
        $attachments[$val->ID] = $_attachments[$key];
    }
} elseif ( ! empty( $atts['exclude'] ) ) {
    $attachments = get_children( array( 'post_parent' => $id, 'exclude' => $atts['exclude'], 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $atts['order'], 'orderby' => $atts['orderby'] ) );
} else {
    $attachments = get_children( array( 'post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $atts['order'], 'orderby' => $atts['orderby'] ) );
}
if ( empty( $attachments ) ) {
    return '';
}
if ( is_feed() ) {
    $output = "\n";
    foreach ( $attachments as $att_id => $attachment ) {
        $output .= wp_get_attachment_link( $att_id, $atts['size'], true ) . "\n";
    }
    return $output;
}
$itemtag = tag_escape( $atts['itemtag'] );
$captiontag = tag_escape( $atts['captiontag'] );
$icontag = tag_escape( $atts['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( $atts['columns'] );
$itemwidth = $columns > 0 ? floor(100/$columns) : 100;
$float = is_rtl() ? 'right' : 'left';
$selector = "gallery-{$instance}";
$gallery_style="";

So this is what I did to get it working(though kind of ugly) so now I can input or just and it’ll grab the images and display them, but in the visual editor it’ll say no items found but when I actually view the post it does show up in the page, now another issue is I need it to be responsive for mobile users so when the screen shrinks down it’ll turn into a slider or slideshow.

Edit

Never mind! my code is buggy and displays every image added instead of going by category, would there be an easy way to fix this?

1 Answer
1

There are various ways to run another WP_Query with a tax query and collect the ID’s into the include attribute of the gallery shortcode.

Let’s try another approach, without running a secondary WP_Query.

Native gallery: Support taxonomy and term attributes

We introduce the following custom gallery shortcode attributes:


Here’s a demo plugin that supports that through the post_gallery, shortcode_atts_gallery filters and the pre_get_posts action:

<?php
/**
 * Plugin Name: Native Gallery Shortcode With Taxonomy And Term Filter Support
 * Description: Add support for 
 * Plugin URI:  http://wordpress.stackexchange.com/a/257801/26350
 */

namespace WPSE\Q257743;

class Gallery
{
    private $term;
    private $taxonomy;

    public function init()
    {
        add_filter( 'post_gallery', [$this, 'post_gallery'], 10, 2 );               
    }

    public function post_gallery( $html, $attr )
    {
        // Check user input for term and taxonomy
        if( empty( $attr['term'] ) || empty( $attr['taxonomy'] ) )
            return $html;

        // Validate taxonomy
        if( ! taxonomy_exists( $attr['taxonomy'] ) )
            return esc_html__( "Taxonomy doesn't exists!", 'wpse-257743' );

        // Validate term
        if( ! term_exists( $attr['term'] , $attr['taxonomy'] ) )
            return esc_html__( "Term doesn't exists!", 'wpse-257743' );

        $this->term     = $attr['term'];
        $this->taxonomy = $attr['taxonomy'];

        // Activate customization
        add_filter( 'shortcode_atts_gallery',   [$this, 'gallery_atts'] );
        add_action( 'pre_get_posts',            [$this, 'pre_get_posts'] );

        return $html;
    }

    public function gallery_atts( $pairs )
    {
        // Set include to a temporary non empty value (that becomes 0)
        $pairs['include'] = ' ';

        // Only run once per gallery
        remove_filter( current_filter(), __FUNCTION__ );

        return $pairs;
    }

    public function pre_get_posts( \WP_Query $q )
    {
        // Make sure it's attachments query
        if( 'attachment' !== $q->get( 'post_type' ) )
            return;

        $post__in = $q->get( 'post__in' );

        // Target queries with post__in (include)       
        if ( empty( $post__in ) )
            return;

        // Check for our temporary 0 value
        if( 1 === count( $post__in ) && 0 != $post__in[0] )
            return;

        $q->set( 'post__in', null );

        // Set the taxonomy query:
        $q->set( 'tax_query', 
            [
                [
                    'taxonomy'  => $this->taxonomy,
                    'field'     => 'slug',
                    'terms'     => $this->term,
                ]
            ]
        );

        // Adjust the number of images to e.g. max 100
        $q->set( 'posts_per_page', 100 );

        // Only run once per gallery
        remove_action( current_action(), __FUNCTION__ );
    }

}

add_action( 'init', [new Gallery, 'init' ] );

Note that here we added a limit of 100 images.

Hope you can test and adjust it further to your needs, and e.g. change it so it can support multiple terms.

Leave a Comment