Out of the box, CPTUI-Extended comes with a healthy number of shortcodes. These shortcodes help you achieve a wide variety of content display. From showing a list of posts, displaying a slider, and all the way to ecommerce products, you can achieve a lot. At the time of writing, there are nine different available shortcodes made readily available.

What happens when your needs are not already available? Say you have a shortcode idea you would like for your users, but it is not in the existing list. CPTUI-Extended has you covered. Through available hooks and filters, you can create your own shortcodes.

Expect the unexpected in the kingdom of madness.

To create your own, you will need to use three different provided hooks. The first is going to be the “cptui_loaded” hook that will register the shortcode. The second is the “cptui_extended_template_paths” filter. This informs CPTUI-Extended where to find the template file. The third is “cptui_filter_query” to set the arguments for a WP_Query call. You will also need a function to configure the modal popup UI. Lastly, you will need to provide the template used when rendering the shortcode. Do not worry; we will cover everything below.

For today’s example, we will create a shortcode that displays a random post from a selected post type. The result will be the featured image, with an optional caption based on the post title.

We are going to use a PHP class in order to load everything into the aforementioned hooks. This class will wire up the hooks and callbacks for you. For brevity sake, code examples will only show key individual parts. The full code will be available at the end.

Snap into a shortcode.

We will begin by showing how to register a shortcode. These steps will make it available in the CPTUI-Extended dropdowns.

First up, we will create a function that invokes the “cptui_register_shortcode()” function. The primary detail is that the first parameter specifies a callable function. This function will create and specify available modal popup options. Since we are creating everything in a class, we will need to pass the callback as shown, and named “random.”

public function register_shortcode() {
    cptui_register_shortcode( array( $this, 'random' ) );
}

Here, we create a PHP method named “register_shortcode” to invoke this function. The “register_shortcode” is the callback method for the “cptui_loaded” hook. This way, it is not loaded until everything we need has already loaded.

Next, we need to create a method named “random.” In this “random” method, we configure the modal popup to display our intended options. These options will include a custom title, which post type to choose from, and if a caption should show.

If you are already familiar with the CMB2 Library, then specifying items will be easy. If you are not, then this CMB2 wiki resource will be invaluable. For our example today, we only need a text input for the title and two select inputs. The first select input specifies which post type to choose from. The second dictates if the caption should show.

public function random() {
    $options = array();
    $types = cptuiext_get_post_type_slugs();
    foreach ( $types as $type ) {
        $options[ $type ] = $type;
    }
    $shortcode = array(
        'id'                => 'random',
        'name'              => __( 'Random Post', 'cptui-extended-random' ),
        'template'          => 'random',
        'template_location' => $this->path . 'templates/',
        'style'             => 'cptui_default_css',
        'post_type'         => 'all',
        'description'       => __( 'Display a random post', 'cptui-extended-random' ),
        'fields'            => array(
            array(
                'name'        => __( 'Title', 'cptui-extended-random' ),
                'id'          => 'title',
                'description' => __( 'Title to display above chosen random post', 'cptui-extended-random' ),
                'type'        => 'text',
            ),
            array(
                'name'        => __( 'Choose post type', 'cptui-extended-random' ),
                'description' => __( 'Post type to choose random post from.', 'cptui-extended-random' ),
                'id'          => 'post_type',
                'type'        => 'select',
                'default'     => 'none',
                'options'     => $options,
            ),
            array(
                'name'    => __( 'Show post title as caption', 'cptui-extended-random' ),
                'id'      => 'show_caption',
                'type'    => 'select',
                'default' => 'true',
                'options' => array(
                    'true'  => 'True',
                    'false' => 'False',
                ),
            ),
        ),
    );

    return $shortcode;
}

To aid in setting up our post type option, we do a quick foreach loop to create an array of post types. The “cptuiext_get_post_type_slugs” function returns an indexed array. Since we need to create a named array, we are doing a quick conversion.

For the “$shortcode” configuration array, the key parts we want to specify are as follows.

The “name” index is the value that gets shown in the dropdown of available shortcodes. The “template” index specifies the file name for the intended template. It should match everything before the “.php” suffix. The “post_type” index should specify which post types it should appear for. This is the first dropdown that shows in the modal popup. In our case, it does not matter, so we specify the key word of “all.” Finally, we have the “fields” index which expects an array of arrays. Each nested array will create the individual field to render.

In the needed post type dropdown, we will provide the “$options” variable we created earlier. The optional title is a text field, and the caption option is a true/false dropdown. After the fields are set, we return “$shortcode” variable to CPTUI-Extended.

At this point, the shortcode should be available when inserting a CPTUI-Extended shortcode. It is not going to do anything yet, though.

Too hot to handle, too cold to hold.

The next hook that we need to use will tell CPTUI-Extended where to find your custom template.

public function filter_paths( $paths = array() ) {
    $paths[15] = $this->path . 'templates/';

    return $paths;
}

CPTUI-Extended 1.4.x includes a new template loader, enabling easy template customization. With that came a detail about a narrower scope of where the plugin loaded template files from. Due to this, we need to create a filter that adds our custom template location to the checked stack. This callback should attach to the “cptui_extended_template_paths” filter. It will have an array of existing locations passed to it, and you can add your own before returning.

The template loader checks child themes first, at a priority of 1, parent themes at a priority of 10. Last it will check CPTUI-Extended’s templates directory at a priority of 100. Our example will insert our plugin file’s template directory path, at a priority of 15. This will make the location checked after the parent theme. Once we return the array of path locations, we can carry on.

Every sport has its own cast of characters.

At this point, we need to set up the arguments to pass to the WP_Query call. These arguments will get used in the template file later.

public function filter_query( $args = array(), $attributes = array() ) {
    if ( 'random' !== $attributes['cptui_shortcode'] ) {
        return $args;
    }

    $args = array(
        'post_type'      => $attributes['post_type'],
        'post_status'    => 'publish',
        'posts_per_page' => '1',
        'orderby'        => 'rand',
    );

    return $args;
}

This callback will accept two different arguments. The first one is the arguments to pass into a WP_Query call. The second is the attributes found on the currently parsed shortcode.

You can have many shortcodes of many varieties on the same page, and because of that, we want to make sure we are dealing with “random” post shortcodes before proceeding. Once we know we are, we proceed to construct our own WP_Query arguments. For our “random” post shortcode, we need to pass in the chosen post type. We then need to specify that we want only published posts, only want one total, and want it selected at random. Once done, we return the variable.

Let me tell you now a man of my position can afford to look ridiculous at any time.

<?php

/**
 * Parses the passed attributes.
 */
$attributes = (array) cptui_shortcode_atts( $attributes );

$custom_query = new WP_Query( cptui_filter_query( $attributes ) );
?>
<div class="cptui-shortcode-random cptui-random-<?php echo esc_attr( $attributes['cptui_shortcode_id'] ); ?>">
    <?php if ( $attributes['title'] ) { ?>
        <h2><?php echo esc_html( $attributes['title'] ); ?></h2>
    <?php } ?>
    <?php while ( $custom_query->have_posts() ) : $custom_query->the_post(); ?>
        <figure class="random-image random-image-<?php the_ID(); ?>">
            <a href="<?php the_permalink(); ?>">
        <?php
            the_post_thumbnail(
                'medium',
                array(
                    'alt' => __( 'Featured image for displayed random post.', 'cptui-extended-random' ),
                )
            );
        ?>
            </a>
        <?php if ( 'true' === $attributes['show_caption'] ) { ?>
            <figcaption><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></figcaption>
        <?php } ?>
        </figure>
    <?php endwhile; ?>
</div>
<?php
wp_reset_postdata();

Finally, we need to set up our template file to query for and display the results. The default CPTUI-Extended templates pass the “$attributes” variable through cptui_shortcode_atts(). This allows others one last chance to filter the arguments before making the query. We also cast the variable to an array. This is due to the new template loader returning a PHP object by default. If you would prefer working with an object instead, you may omit the casting. At this point, all that remains is instantiating and iterating over a new WP_Query object.

If you’ve created or customized the WordPress Loop, this will be familiar. For our random image output, we are providing a wrapping div and a couple of classes. Here I am utilizing the generated shortcode ID value as part of one class. This way, a user could target a very specific random shortcode, if desired. Next, I output a heading tag, if we have a title provided. For our random image, we are going to use the “figure” and “figcaption” html tags. Inside the figure tag, we output the post’s featured image at the “medium” size. We have also added an alt tag for accessibility purposes. If we have chosen to display the post title as a photo caption, we display that inside the “figcaption” tag. We have also linked both the image and the caption to the selected post.

The Mega-Powers explode.

If everything has gone well for you, you should have a full, working random post shortcode. It will work anywhere available that can handle shortcodes. This will include posts, pages, post types.

Full plugin: cptui-extended-random

If you have any questions or need some help, drop in a comment below.

Have a comment? Leave a reply

Your email address will not be published.