Create An Image Slide Plugin Part 7: Create WordPress Shortcodes

Create An Image Slide Plugin Part 7: Create WordPress Shortcodes

In the seventh post from this series we’re going to talk about how to create your own WordPress shortcodes in order to display the slides and sliders we created.

The previous post in which we added custom metadata to our mnsp_slider taxonomy terms, was the last post focusing only on the admin side. Starting now we’re also going to step into the public side with the ability to show the slides and sliders on different pages.

What Are WordPress Shortcodes?

The WordPress Plugin Handbook calls shortcodes, macros that can be used to perform dynamic interactions with the content.

If you ask Google, it will tell you that a macro is a single instruction that expands automatically into a set of instructions to perform a particular task.

So, combining the two definitions, we can refer to a shortcode as a small piece of code, written in brackets like [this], that performs specific functions in a website by running some code that is provided by the developer of that shortcode.

Shortcodes were introduced in WordPress 2.5 to allow interaction with the content as, for security concerns, running PHP inside WordPress content is forbidden.

The very basic shortcode is defined by a tag like this:

[shortcode_tag]

More complex shortcodes can contain attributes like this:

[shortcode_tag attr1="value1" attr2="value2"] 

Shortcodes can also contain custom content in which case they will end with a closing tag like this:

[shortcode_tag attr="value"] Some content here [/shortcode_tag] 

In order for WordPress to know what to do when it encounters a shortcode, we must provide it with a piece of code that it will then run.

How To Create WordPress Shortcodes?

If you want to follow along I’ve set up a GitHub repository where you’ll find the code from this series. The finished code for this post is in the part_7 branch. If you want to follow along please download the part_6 branch.

For this plugin, we’ll create two shortcodes, mnsp_slide and mnsp_slider, to show a single slide or a slider.

We’ll start with creating a class file to hold the shortcodes functionality. So, let’s create a new file called class-monospace-slides-shortcodes.php in the /includes  folder of our plugin.

We’re working in this folder because the shortcodes functionality is present on the admin side as well as the public facing side of WordPress.

In the new file we’re creating a class to hold all the methods that the shortcodes are using.

<?php

/**
 * The functionality for creating and managing shortcodes.
 *
 * @link       https://www.mikeinmonospace.com/
 * @since      1.0.0
 *
 * @package    Monospace_Slides
 * @subpackage Monospace_Slides/includes
 */

/**
 * The functionality for creating and managing shortcodes.
 *
 * Defines all the functionality related to the creation and managing of shortcodes.
 *
 * @package    Monospace_Slides
 * @subpackage Monospace_Slides/includes
 * @author     Mike In Monospace <mikeinmonospace@gmail.com>
 */
class Monospace_Slides_Shortcodes {



}

Next, we’re updating the class with two methods for registering and displaying our shortcodes. The code below goes inside the class we created earlier and we’ll go though it step by step:

/**
 * Create and register the 'mnsp_slide' shortcode for displaying a single slide.
 *
 * @since 1.0.0
 */
public function register_slide_shortcode() {

	/**
	 * Handler function for the 'mnsp_slide' shortcode.
	 *
	 * @since 1.0.0
	 * @param array $atts    Shortcode attributes.
	 */
	function slide_shortcode( $atts ) {

		$args = shortcode_atts(
			array(
				'id' => '',
			),
			$atts
		);

		$id = (int) $args['id'];

		$title       = esc_html( get_post_meta( $id, 'mnsp-slide-title', true ) );
		$title_color = esc_attr( get_post_meta( $id, 'mnsp-slide-title-color', true ) );

		$subtitle       = esc_html( get_post_meta( $id, 'mnsp-slide-subtitle', true ) );
		$subtitle_color = esc_attr( get_post_meta( $id, 'mnsp-slide-subtitle-color', true ) );

		$desc       = esc_textarea( get_post_meta( $id, 'mnsp-slide-desc', true ) );
		$desc_color = esc_attr( get_post_meta( $id, 'mnsp-slide-desc-color', true ) );

		$cta_text           = esc_html( get_post_meta( $id, 'mnsp-slide-cta-text', true ) );
		$cta_text_color     = esc_attr( get_post_meta( $id, 'mnsp-slide-cta-text-color', true ) );
		$cta_bg_color       = esc_attr( get_post_meta( $id, 'mnsp-slide-cta-bg-color', true ) );
		$cta_hover_bg_color = esc_attr( get_post_meta( $id, 'mnsp-slide-cta-hover-bg-color', true ) );
		$cta_url            = esc_url( get_post_meta( $id, 'mnsp-slide-cta-url', true ) );
		$cta_target         = esc_attr( get_post_meta( $id, 'mnsp-slide-cta-target', true ) ) ? '_blank' : '_self';

		$image = esc_url( get_post_meta( $id, 'mnsp-slide-image', true ) );

		$horiz_align = esc_attr( get_post_meta( $id, 'mnsp-slide-horiz-align', true ) );

		$ratio = esc_attr( get_post_meta( $id, 'mnsp-slide-ratio', true ) );

		$feat_img_opacity = esc_attr( get_post_meta( $id, 'mnsp-slide-featured-opacity', true ) );

		$bg_color = esc_attr( get_post_meta( $id, 'mnsp-slide-bg-color', true ) );

		$has_thumbnail = has_post_thumbnail( $id ) ? ' mnsp-slide-has-thumbnail' : '';

		$slide = '<div 
			id="mnsp-slide-' . $id . '" 
			class="mnsp-slide' . $has_thumbnail . '" 
			data-mnsp-slide-title-color="' . $title_color . '" 
			data-mnsp-slide-subtitle-color="' . $subtitle_color . '"
			data-mnsp-slide-desc-color="' . $desc_color . '" 
			data-mnsp-slide-cta-text-color="' . $cta_text_color . '" 
			data-mnsp-slide-cta-bg-color="' . $cta_bg_color . '" 
			data-mnsp-slide-cta-hover-bg-color="' . $cta_hover_bg_color . '" 
			data-mnsp-slide-horiz-align="' . $horiz_align . '" 
			data-mnsp-slide-ratio="' . $ratio . '" 
			data-mnsp-slide-featured-opacity="' . $feat_img_opacity . '" 
			data-mnsp-slide-bg-color="' . $bg_color . '">';

		$slide .= '<div class="mnsp-slide-caption">';

		if ( ! empty( $image ) ) {
			$slide .= '<img class="mnsp-slide-image" src="' . $image . '" />';
		}

		if ( ! empty( $title ) ) {
			$slide .= '<p class="mnsp-slide-title">' . $title . '</p>';
		}

		if ( ! empty( $subtitle ) ) {
			$slide .= '<p class="mnsp-slide-subtitle">' . $subtitle . '</p>';
		}

		if ( ! empty( $desc ) ) {
			$slide .= '<p class="mnsp-slide-desc">' . $desc . '</p>';
		}

		if ( ! empty( $cta_text ) && ! empty( $cta_url ) ) {
			$slide .= '<a class="mnsp-slide-cta" href="' . $cta_url . '" target="' . $cta_target . '">' . $cta_text . '</a>';
		}

		$slide .= '</div>';

		$slide .= get_the_post_thumbnail( $id, 'mnsp-image-' . $ratio, array( 'class' => 'mnsp-slide-featured' ) );

		$slide .= '</div>';

		return $slide;

	}

	add_shortcode( 'mnsp_slide', 'slide_shortcode' );

}

/**
 * Register the 'mnsp_slider' shortcode for displaying multiple slides in a slider.
 *
 * @since    1.0.0
 */
public function register_slider_shortcode() {

	function slider_shortcode( $atts ) {

		extract( shortcode_atts( array(
			'id' => ''
		), $atts ) );

		return 'id is ' . $id;

	}

	add_shortcode( 'mnsp_slider', 'slider_shortcode' );

}

These two methods contain the functionality for registering and displaying the shortcodes. The method for displaying the slide shortcode is complete and we’ll build the method for displaying a slider in a future post.

Looking at the first method for registering and displaying a single slide we can see that it contains a function declaration and a function call.

The function call to add_shortcode() tells WordPress about the mnsp_slide shortcode and it also tells it to use the function above to unpack and display that shortcode when it is encountered.

Looking at the function declaration, it starts with taking the id parameter from the shortcode declaration and making it available as a variable inside the function, by using the extract() function.

Next, we’re creating a few more variables by reading the metadata of a single slide, based on the id variable we created earlier.

Finally, we’re building the HTML code for displaying a single slide by using the variables we created earlier.

Next, we’re going to add and populate two admin columns that will contain the exact shortcode declaration that we’ll use in our posts and pages for displaying slides and sliders. So, we’ll just do a copy + paste of the content of these columns.

/**
 * Creates a new admin column on the custom post type listing screen that will display the slide shortcode.
 *
 * @since 1.0.0
 * @access public
 */
public function add_slide_columns( $columns ) {

	$columns['shortcode'] = __( 'Shortcode', 'monospace-slides' );
	
	return $columns;

}

/**
 * Displays the slide shortcode in an admin column called 'shortcode'.
 *
 * @since 1.0.0
 * @access public
 */
function add_slide_columns_content( $column, $post_id ){

	if ( 'shortcode' === $column ) {
		echo '[mnsp_slide id="' . $post_id . '"]';
	}

}

/**
 * Creates a new admin column on the custom taxonomy listing screen that will display the slider shortcode.
 *
 * @since 1.0.0
 * @access public
 */
public function add_slider_columns( $columns ) {

	$columns['shortcode'] = __( 'Shortcode', 'monospace-slides' );
	
	return $columns;

}

/**
 * Displays the slider shortcode in an admin column called 'shortcode'.
 *
 * @since 1.0.0
 * @access public
 */
function add_slider_columns_content( $content, $column_name, $term_id ){

	if ( 'shortcode' === $column_name ) {
		$content = '[mnsp_slider id="' . $term_id . '"]';
	}

	return $content;
}

The first two methods create and populate a column for the slide shortcode. The next two methods are similar but for the slider shortcode.

Next we’ll add some CSS and JS code for displaying a single slide. The code below will go in two files from the /public folder, as it loads only on the public facing side of the website. These files should already be present inside the plugin folder structure.

So, the CSS code below goes in /public/css/monospace-slides-public.css file. Put this code inslide the function that already exists in the file.

.mnsp-slide {
	position: relative;
	padding: 0 !important;
}

.mnsp-slide {
	display: flex;
	height: auto;
	justify-content: center;
	align-items: center;
	font-size: 1rem;
	overflow: hidden;
}

.mnsp-slide::before { /* for the aspect ratio functionality */
	content: "";
	width: 1px;
	margin-left: -1px;
	float: left;
	height: 0;
}

.mnsp-slide::after { /* to clear float */
	content: "";
	display: table;
	clear: both;
}

.mnsp-slide[data-mnsp-slide-horiz-align="left"] .mnsp-slide-caption {
	text-align: left;
}

.mnsp-slide[data-mnsp-slide-horiz-align="center"] .mnsp-slide-caption {
	text-align: center;
}

.mnsp-slide[data-mnsp-slide-horiz-align="right"] .mnsp-slide-caption {
	text-align: right;
}

.mnsp-slide-caption {
	position: relative;
	width: 100%;
	padding: 5vmin;
	z-index: 2000;
}

.mnsp-slide-image {
	max-width: 15%;
}

.mnsp-slide-title {
	font-size: 1.25em;
}

.mnsp-slide-subtitle {
	font-size: 1.1em;
}

.mnsp-slide .mnsp-slide-caption .mnsp-slide-cta,
.mnsp-slide .mnsp-slide-caption .mnsp-slide-cta:hover,
.mnsp-slide .mnsp-slide-caption .mnsp-slide-cta:focus,
.mnsp-slide .mnsp-slide-caption .mnsp-slide-cta:active {
	color: white;
	text-decoration: none;
	border: 0;
	box-shadow: none;
}

.mnsp-slide .mnsp-slide-caption .mnsp-slide-cta {
	display: inline-block;
	font-family: Raleway, "Open Sans", "Source Sans Pro", sans-serif;
	font-size: smaller;
	font-weight: bold;
	text-transform: uppercase;
	line-height: 1;
	padding: 16px 30px;
	background-color: black;
	cursor: pointer;
	transition: all 0.5s ease;
}

.mnsp-slide-caption > * + * {
	margin: 0.75rem 0 0 0;
}

.mnsp-slide-featured {
	position: absolute;
	height: 100%;
	object-fit: cover;
	z-index: 1000;
}

.mnsp-slide[data-mnsp-slide-ratio="wide"]::before {
	padding-top: 56.25%;
}

.mnsp-slide[data-mnsp-slide-ratio="classic"]::before {
	padding-top: 75%;
}

.mnsp-slide[data-mnsp-slide-ratio="square"]::before {
	padding-top: 100%;
}

The JS code below goes in /public/js/monospace-slides-public.js file:

var slides  = document.querySelectorAll( '.mnsp-slide' );

slides.forEach( function( slide ) {

	var $this 		= slide,
		title 		= $this.querySelector( '.mnsp-slide-title' ),
		subTitle 	= $this.querySelector( '.mnsp-slide-subtitle' ),
		desc 		= $this.querySelector( '.mnsp-slide-desc' ),
		cta 		= $this.querySelector( '.mnsp-slide-cta' ),
		featured 	= $this.querySelector( '.mnsp-slide-featured' );

	if ( title ) {
		title.style.color = $this.dataset.mnspSlideTitleColor;
	}

	if ( subTitle ) {
		subTitle.style.color = $this.dataset.mnspSlideSubtitleColor;
	}

	if ( desc ) {
		desc.style.color = $this.dataset.mnspSlideDescColor;
	}

	if ( cta ) {
		cta.style.color = $this.dataset.mnspSlideCtaTextColor;
		cta.style.backgroundColor = $this.dataset.mnspSlideCtaBgColor;

		cta.addEventListener( 'mouseover', function() {
			$this.querySelector( '.mnsp-slide-cta' ).style.backgroundColor = $this.dataset.mnspSlideCtaHoverBgColor;
		}, false );

		cta.addEventListener( 'mouseout', function() {
			$this.querySelector( '.mnsp-slide-cta' ).style.backgroundColor = $this.dataset.mnspSlideCtaBgColor;
		}, false );
	}

	$this.style.backgroundColor = $this.dataset.mnspSlideBgColor;

	if ( featured ) {
		featured.style.opacity = $this.dataset.mnspSlideFeaturedOpacity;
	}

} ); // eslint-disable-line

In the final part of this tutorial, we are going to tell WordPress to use all the previous code to create the custom shortcodes functionality.

We’ll start by adding the custom shortcodes class file as a dependency in the Monospace_Slides class located in the /includes/class-monospace-slides.php file.

Add the following code inside the load_dependencies() method, after requiring the taxonomy term meta class file.

/**
 * The class responsible for the functionality of the shortcodes.
 */
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-monospace-slides-shortcodes.php';

This makes sure that the methods inside the Monospace_Slides_Shortcodes are present and ready to be called when WordPress needs them.

Next, add the method below, after the define_term_meta_hooks() method within that same file:

/**
 * Register all the hooks needed for shortcodes functionality
 *
 * @since 		1.0.0
 * @access 		public
 */
public function define_shortcodes_hooks() {

	$plugin_shortcodes = new Monospace_Slides_Shortcodes();
	
	$this->loader->add_action( 'init', $plugin_shortcodes, 'register_slide_shortcode' );
	$this->loader->add_action( 'init', $plugin_shortcodes, 'register_slider_shortcode' );

	$this->loader->add_filter( 'manage_edit-mnsp_slide_columns', $plugin_shortcodes, 'add_slide_columns' );
	$this->loader->add_filter( 'manage_mnsp_slide_posts_custom_column', $plugin_shortcodes, 'add_slide_columns_content', 10, 2 );

	$this->loader->add_filter( 'manage_edit-mnsp_slider_columns', $plugin_shortcodes, 'add_slider_columns' );
	$this->loader->add_filter( 'manage_mnsp_slider_custom_column', $plugin_shortcodes, 'add_slider_columns_content', 10, 3 );

}

The method above uses the methods from the Monospace_Slides_Shortcodes class to register the shortcodes and create the custom admin columns.

Lastly, at the end of the __construct() method call the method we created above as so:

$this->define_shortcodes_hooks();

Now, WordPress knows about the new shortcodes which are ready to be used.

Provided you added the code from this tutorial to the plugin in your WordPress installation and have created some slides, the slides listing screen should look like this:

Slide Custom WordPress Shortcode Admin Column

To display a slide just copy the content of the Shortcode column, including the square brackets and paste it in any post or page.

At The End

We went through a lot of code in this tutorial. We now know hot to create custom WordPress shortcodes as well as display custom content using them.

In the next tutorial from this series we’ll build the functionality for displaying multiple slides into an animated slider. As you remember we only built the basic function for doing that earlier in the start of this tutorial.

In the meantime, please feel free to share your thoughts and opinions on the contents of this tutorial and I’ll make sure to address all the issues.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.