0

I'm building two metabox galleries on the same page with the help of a tutorial. The code works fine. However the galleries are automatically displayed after the content on the front end.

What I would like to do is to display each gallery wherever I want in my template page, not automatically after the content.

Here is the PHP code in my functions.php:

/**
 *  Sortable WordPress Gallery class to create gallery metabox and save it
 */
class Sortable_WordPress_Gallery {

    /**
     * Unique ID of the metabox
     * @var string
     */
    protected $id;

    /**
     * Metabox Title
     * @var string
     */
    protected $title = '';

    /**
     * Metabox Context
     * @var string
     */
    protected $context = 'advanced';

    /**
     * Metabox Priority
     * @var string
     */
    protected $priority = 'high';

    /**
     * Hook into the appropriate actions when the class is constructed.
     */
    public function __construct( $id, $title = '', $context = 'advanced', $priority = 'high'  ) {

        // ID is required
        if( $id == '' ) {
            return;
        }

        $this->id = $id;

        // Create title from ID if not provided
        if( $title == '' ) {
            $this->title = ucfirst( $id );
        } else {
            $this->title = $title;
        }

        // Only valid context can be changed
        $available_context = array(
            'advanced',
            'side',
            'normal');
        if( in_array( $context, $available_context ) ) {
            $this->context = $context;
        }

        // Only valid priorty can be changed
        $available_priority = array(
            'default',
            'high',
            'low');
        if( in_array( $priority, $available_priority ) ) {
            $this->priority = $priority;
        }

        add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
        add_action( 'save_post',      array( $this, 'save' ) );
        add_filter( 'the_content', array( $this, 'render' ) );
    }

    /**
     * Adds the meta box container.
     */
    public function add_meta_box( $post_type ) {

        // Limit meta box to certain post types.
        // Can be extended using filter 'sortable_wordpress_gallery_post_types' or
        // using a dynamic filter 'sortable_wordpress_gallery_METABOX-ID_post_types'
        $post_types = apply_filters( 'sortable_wordpress_gallery_post_types', array( 'page' ) );
        $post_types = apply_filters( 'sortable_wordpress_gallery_' . $this->id .  '_post_types',  $post_types );

        if ( in_array( $post_type, $post_types ) ) {
            add_meta_box(
                $this->id,
                $this->title,
                array( $this, 'render_meta_box_content' ),
                $post_type,
                $this->context,
                $this->priority
                );
        }
    }

    /**
     * Render Meta Box content.
     *
     * @param WP_Post $post The post object.
     */
    public function render_meta_box_content( $post ) {


        // Add an nonce field so we can check when saving
        wp_nonce_field( $this->id . '_metabox', $this->id . '_metabox_nonce' );

      // Get the gallery saved data
        $sortable_gallery = get_post_meta( $post->ID, '_' . $this->id . '_sortable_wordpress_gallery', true );

        ?>
        <table class="table">
            <tr>
                <th style="vertical-align: top;">
                    <?php _e( 'Slider Images', 'your_text_domain' ); ?>
                </th>
                <td>
                  <!-- Creating a dynamic ID using the metabox ID for JavaScript-->
                    <ul id="<?php echo $this->id; ?>_sortable_wordpress_gallery" class="sortable_wordpress_gallery">
                        <?php
                        // Getting all the image IDs by creating an array from string ( 1,3,5 => array( 1, 3, 5) )
                        $gallery = explode(",", $sortable_gallery );

                      // If there is any ID, create the image for it
                        if( count( $gallery ) > 0 && $gallery[0] != '' ) {
                            foreach ( $gallery as $attachment_id ) {

                              // Create a LI elememnt
                                $output = '<li tabindex="0" role="checkbox" aria-label="' . get_the_title( $attachment_id ) . '" aria-checked="true" data-id="' . $attachment_id . '" class="attachment save-ready selected details">';
                                 // Create a container for the image. (Copied from the WP Media Library Modal to use the same styling)
                                  $output .= '<div class="attachment-preview js--select-attachment type-image subtype-jpeg portrait">';
                                    $output .= '<div class="thumbnail">';

                                      $output .= '<div class="centered">';
                                       // Get the URL to that image thumbnail
                                        $output .= '<img src="'  . wp_get_attachment_thumb_url( $attachment_id ) . '" draggable="false" alt="">';
                                      $output .= '</div>';

                                    $output .= '</div>';

                                  $output .= '</div>';
                                // Add the button to remove this image if wanted (we set the data-gallery to target the correct gallery if there are more than one)
                                  $output .= '<button type="button" data-gallery="#' . $this->id . '_sortable_wordpress_gallery" class="button-link check remove-sortable-wordpress-gallery-image" tabindex="0"><span class="media-modal-icon"></span><span class="screen-reader-text">Deselect</span></button>';

                                $output .= '</li>';
                                echo $output;
                            }
                        }
                        ?>
                    </ul>
                    <!-- Hidden input used to save the gallery image IDs into the database -->
                    <!-- We are also creating dynamic IDs here so that we can easily target them in JavaScript -->
                    <input type="hidden" id="<?php echo $this->id; ?>_sortable_wordpress_gallery_input" name="_<?php echo $this->id; ?>_sortable_wordpress_gallery" value="<?php echo $sortable_gallery; ?>" />
                    <!-- Button used to open the WordPress Media Library Modal -->
                    <button type="button" class="button button-primary add-sortable-wordpress-gallery" data-gallery="#<?php echo $this->id; ?>_sortable_wordpress_gallery"><?php _e( 'Add Images', 'your_text_domain' ); ?></button>
                </td>
            </tr>
        </table>
        <?php
    }


    /**
     * Save the meta when the post is saved.
     *
     * @param int $post_id The ID of the post being saved.
     */
    public function save( $post_id ) {

        /*
         * We need to verify this came from the our screen and with proper authorization,
         * because save_post can be triggered at other times.
         */

        // Check if our nonce is set.
        if ( ! isset( $_POST[ $this->id . '_metabox_nonce'] ) ) {
            return $post_id;
        }

        $nonce = $_POST[ $this->id . '_metabox_nonce'];

        // Verify that the nonce is valid.
        if ( ! wp_verify_nonce( $nonce, $this->id . '_metabox' ) ) {
            return $post_id;
        }

        /*
         * If this is an autosave, our form has not been submitted,
         * so we don't want to do anything.
         */
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
            return $post_id;
        }

        // Check the user's permissions.
        if ( 'page' == $_POST['post_type'] ) {
            if ( ! current_user_can( 'edit_page', $post_id ) ) {
                return $post_id;
            }
        } else {
            if ( ! current_user_can( 'edit_post', $post_id ) ) {
                return $post_id;
            }
        }

        /* OK, it's safe for us to save the data now. */
        $gallery = sanitize_text_field( $_POST[ '_' . $this->id . '_sortable_wordpress_gallery' ] );

        // Update the meta field.
        update_post_meta( $post_id, '_' . $this->id . '_sortable_wordpress_gallery', $gallery );

    }


    /**
   * Rendering the gallery
   */
  public function render( $content ) {
    global $post;

    // Get our registered post types
    $post_types = apply_filters( 'sortable_wordpress_gallery_post_types', array( 'page' ) );
    $post_types = apply_filters( 'sortable_wordpress_gallery_' . $this->id .  '_post_types',  $post_types );

    // Get current post type
    $this_post_type = get_post_type( $post );

    // If the current post type is also a registered post type, create the gallery
    if( in_array( $this_post_type, $post_types ) ) {
        // Get all the image IDs
        $gallery_images = get_post_meta( $post->ID, '_' . $this->id . '_sortable_wordpress_gallery', true );
            if( $gallery_images != '' ) {
              // If the data retrieved is not empty, create an array
                $gallery_images_array = explode( ',', $gallery_images );
                //Create a gallery container with the 3 column layout
                $content .= '<div class="gallery" style="display: flex;">';
                // For each image ID, create the gallery image
                foreach ( $gallery_images_array as $image_id ) {

                $html = wp_get_attachment_image( $image_id );
            if( $html == '' ) {
              continue;
            }

            $content .= '<div class="gallery-item">';
              $content .= '<a href="' . get_permalink( $image_id ) . '" target="_blank">';
                $content .= $html;
              $content .= '</a>';
            $content .= '</div>';
          }

                $content .= '</div>';
            }
     }

        return $content;
    }


}



/**
 * WordPress Gallery Factory
 */
class Sortable_WordPress_Galleries {

    /**
     * Gallery Defaults
     * @var array
     */
    protected $gallery_defaults = array(
            'class' => 'Sortable_WordPress_Gallery',
            'id' => '',
            'title' => '',
            'context' => '',
            'priority' => '' );

    /**
     * Galleries that have been registered to use
     * @var array
     */
    protected $galleries = array();

    /**
     * Loaded galleries (Gallery objects)
     * @var array
     */
    protected $loaded_galleries = array();

    /**
     * Constructor method
     */
    public function __construct() {

        add_action( 'init', array( $this, 'collect_galleries') );
        add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
        add_action( 'admin_init', array( $this, 'create_galleries' ) );
        add_filter( 'the_content', array( $this, 'render_galleries' ) );

    }

    /**
     * Enqueuing admin scripts and styles
     */
    /*
    public function admin_scripts() {
        wp_enqueue_script( 'sortable-gallery-admin-js', plugin_dir_url( __FILE__ ). 'admin.js', array( 'jquery' ) );
            wp_enqueue_style( 'sortable-gallery-admin-css', plugin_dir_url( __FILE__ ). 'admin.css' );
    }*/
    public function admin_scripts() {
        wp_enqueue_script( 'sortable-gallery-admin-js', get_template_directory_uri() . '/gallery-multiple-metabox/js/admin.js', array( 'jquery' ) );
            wp_enqueue_style( 'sortable-gallery-admin-css', get_template_directory_uri() . '/gallery-multiple-metabox/css/admin.css' );
    }

    /**
    * Collect galleries passed to our filter
    */
    public function collect_galleries() {

        $this->galleries = apply_filters( 'sortable_wordpress_galleries', $this->galleries );

    }


    /**
     * Hook our method load_galleries on edit post screens
     */
    public function create_galleries() {
        add_action( 'load-post.php',     array( $this, 'load_galleries' ) );
            add_action( 'load-post-new.php', array( $this, 'load_galleries' ) );

    }

    /**
    * Create gallery objects to create metaboxes
    */
    public function load_galleries() {

        foreach ( $this->galleries as $gallery ) {
            $gallery = wp_parse_args( $gallery, $this->gallery_defaults );
            $class = $gallery['class'];
            if( $class != '' ) {
                $this->loaded_galleries[] = new $class( $gallery['id'], $gallery['title'], $gallery['context'], $gallery['priority'] );
            }

        }
    }


    /**
     * Load all the galleries and render each gallery
     */
    public function render_galleries($content) {
        $this->load_galleries();

        foreach ( $this->loaded_galleries as $gallery ) {

            $content = $gallery->render( $content );

        }

        return $content;
    }
}
new Sortable_WordPress_Galleries();


add_filter( 'sortable_wordpress_galleries', 'add_sortable_gallery' );
function add_sortable_gallery( $galleries ) {
    
    // Gallery metabox #1
    $galleries[] = array(
        'class' => 'Sortable_WordPress_Gallery',
        'id' => 'post-metabox',
        'title' => 'Sortable Gallery'
    );
    
    // Gallery metabox #2
    $galleries[] = array(
        'class' => 'Sortable_WordPress_Gallery',
        'id' => 'post-metabox-2',
        'title' => 'Sortable Gallery-2'
    );

    return $galleries;
}

I'm struggling to find the way how to remove the rendering gallery out of the_content(); and insert the rendering code inside my template.

Thank you.

2
  • You added render method to "the_content" filter. add_filter( 'the_content', array( $this, 'render' ) );. That's why you see gallery with the_content. Perhaps it's possible to add this render method as shortcode. Or you want something else?
    – anton
    Commented May 26, 2021 at 10:38
  • Thank you @anton, you're right. I removed it and now the the gallery doesn't show up inside the_content(); Commented May 26, 2021 at 12:29

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.