Video icon 64
Learning to code? Skill up faster with our practical video courses. Start your free trial today.
Advertisement

Object-Oriented Programming in WordPress - Document The Plugin II

by
Student iconAre you a student? Get a yearly Tuts+ subscription for $45 →

At this point in the series, we're ready to move forward with rounding out our plugin by documenting our files, classes, functions, variables, and more.

Though this is the last step that we actually have to completing the plugin, it's not the last post in the series as we'll continue to look at a few advanced topics in object-oriented programming.

But before we do that, let's bring our plugin up to version 1.0 by putting into practice everything we learned in the previous article.

Of course, as with all previous articles, I recommend catching up on everything that we've covered thus far so you're completely up to speed not only with the work that we've done in the last article, but with how we actually got to the final points we're discussing in this article.

  1. An Introduction
  2. Classes
  3. Types
  4. Control Structures: Conditional Statements
  5. Control Structures: Loops
  6. Functions and Attributes
  7. Scope
  8. Building the Plugin I
  9. Building the Plugin II
  10. Document the Plugin I

With all of those covered and reviewed, let's get started with documenting each of our files.

Documenting the Plugin

There are a number of different ways that we can go about documenting this plugin:

  • We could document all of the file headers first, then we could come back and document the classes, then we could come back and document the variables, then we could document the functions.
  • We could document each file at a time and have a short discussion over everything that's included on a per file basis.

Obviously, the option will yield more documentation per section, but should result in a much less tedious article and a much easier understanding the flow of control for the entire plugin.

To that end, we're going to work through the plugin, file-by-file, introducing documentation for each piece of code that we have and then we'll discuss any points of interest following the code.

Finally, we'll make sure we refer to the final version of the plugin at the end of the article. With that said, let's get started.

The Single Post Meta Manager

Recall that the main file for starting the plugin is the single-post-meta-manager.php file located in the root of the directory of the plugin.

Here's what the fully documented version of the file looks like. Read each comment closely paying attention not only to the format that it follows, but the content that it provides.

<?php
/**
 * The file responsible for starting the Single Post Meta Manager plugin
 *
 * The Single Post Meta Manager is a plugin that displays the post meta data
 * associated with a given post. This particular file is responsible for
 * including the necessary dependencies and starting the plugin.
 *
 * @package SPPM
 *
 * @wordpress-plugin
 * Plugin Name:       Single Post Meta Manager
 * Plugin URI:        http://github.com/tommcfarlin/post-meta-manager
 * Description:       Single Post Meta Manager displays the post meta data associated with a given post.
 * Version:           1.0.0
 * Author:            Tom McFarlin
 * Author URI:        http://tommcfarlin.com
 * Text Domain:       single-post-meta-manager-locale
 * License:           GPL-2.0+
 * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
 * Domain Path:       /languages
 */

// If this file is called directly, then about execution.
if ( ! defined( 'WPINC' ) ) {
    die;
}

/**
 * Include the core class responsible for loading all necessary components of the plugin.
 */
require_once plugin_dir_path( __FILE__ ) . 'includes/class-single-post-meta-manager.php';

/**
 * Instantiates the Single Post Meta Manager class and then
 * calls its run method officially starting up the plugin.
 */
function run_single_post_meta_manager() {

	$spmm = new Single_Post_Meta_Manager();
	$spmm->run();

}

// Call the above function to begin execution of the plugin.
run_single_post_meta_manager();

In the above code, notice that we've defined a file header as per the conventions that we outlined that in the previous article. We also maintained the required plugin header tags in order for WordPress to proper read them.

Note that, in this case, we've included them under a custom @wordpress-plugin tag. This isn't required but helps to separate the file header comments from the required the plugin comments.

Finally, note that we've bumped the version of this plugin up to 1.0, and we've also given this plugin the @package value of SPMM which is short of Single Post Meta Manager. We'll be using this throughout the plugin.

The includes Directory

Next, let's turn our attention to all of the files that are located in the includes directory. 

Since these files are required before anything in the admin directory, it makes sense to look at each of these files individually, and then round out our discussion with the remaining files in the admin directory.

The Single Post Meta Manager

<?php

/**
 * The Single Post Meta Manager is the core plugin responsible for including and
 * instantiating all of the code that composes the plugin
 *
 * @package SPMM
 */

/**
 * The Single Post Meta Manager is the core plugin responsible for including and
 * instantiating all of the code that composes the plugin.
 *
 * The Single Post Meta Manager includes an instance to the Single Post Manager
 * Loader which is responsible for coordinating the hooks that exist within the
 * plugin.
 *
 * It also maintains a reference to the plugin slug which can be used in
 * internationalization, and a reference to the current version of the plugin
 * so that we can easily update the version in a single place to provide
 * cache busting functionality when including scripts and styles.
 *
 * @since    1.0.0
 */
class Single_Post_Meta_Manager {

    /**
	 * A reference to the loader class that coordinates the hooks and callbacks
	 * throughout the plugin.
	 *
	 * @access protected
	 * @var    Single_Post_Meta_Manager_Loader   $loader    Manages hooks between the WordPress hooks and the callback functions.
	 */
	protected $loader;

	/**
	 * Represents the slug of hte plugin that can be used throughout the plugin
	 * for internationalization and other purposes.
	 *
	 * @access protected
	 * @var    string   $plugin_slug    The single, hyphenated string used to identify this plugin.
	 */
	protected $plugin_slug;

	/**
	 * Maintains the current version of the plugin so that we can use it throughout
	 * the plugin.
	 *
	 * @access protected
	 * @var    string   $version    The current version of the plugin.
	 */
	protected $version;

	/**
	 * Instantiates the plugin by setting up the core properties and loading
	 * all necessary dependencies and defining the hooks.
	 *
	 * The constructor will define both the plugin slug and the verison
	 * attributes, but will also use internal functions to import all the
	 * plugin dependencies, and will leverage the Single_Post_Meta_Loader for
	 * registering the hooks and the callback functions used throughout the
	 * plugin.
	 */
	public function __construct() {

		$this->plugin_slug = 'single-post-meta-manager-slug';
		$this->version = '1.0.0';

		$this->load_dependencies();
		$this->define_admin_hooks();

	}



	/**
	 * Imports the Single Post Meta administration classes, and the Single Post Meta Loader.
	 *
	 * The Single Post Meta Manager administration class defines all unique functionality for
	 * introducing custom functionality into the WordPress dashboard.
	 *
	 * The Single Post Meta Manager Loader is the class that will coordinate the hooks and callbacks
	 * from WordPress and the plugin. This function instantiates and sets the reference to the
	 * $loader class property.
	 *
	 * @access    private
	 */
	private function load_dependencies() {

		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-single-post-meta-manager-admin.php';

		require_once plugin_dir_path( __FILE__ ) . 'class-single-post-meta-manager-loader.php';
		$this->loader = new Single_Post_Meta_Manager_Loader();

	}

	/**
	 * Defines the hooks and callback functions that are used for setting up the plugin stylesheets
	 * and the plugin's meta box.
	 *
	 * This function relies on the Single Post Meta Manager Admin class and the Single Post Meta Manager
	 * Loader class property.
	 *
	 * @access    private
	 */
	private function define_admin_hooks() {

		$admin = new Single_Post_Meta_Manager_Admin( $this->get_version() );
		$this->loader->add_action( 'admin_enqueue_scripts', $admin, 'enqueue_styles' );
		$this->loader->add_action( 'add_meta_boxes', $admin, 'add_meta_box' );

	}

	/**
	 * Sets this class into motion.
	 *
	 * Executes the plugin by calling the run method of the loader class which will
	 * register all of the hooks and callback functions used throughout the plugin
	 * with WordPress.
	 */
	public function run() {
		$this->loader->run();
	}

	/**
	 * Returns the current version of the plugin to the caller.
	 *
	 * @return    string    $this->version    The current version of the plugin.
	 */
	public function get_version() {
		return $this->version;
	}

}

Clearly, there are a lot of new comments that have been introduced into this particular file; however, it should be very self-explanatory as to what each class property, the constructor, and the internal functions are doing.

The key thing to notice - aside from how the information is coordinated through out the plugin - is how we've adhered to the standards defined in the previous article. 

Notice, however, that we have taken the liberty if not using certain tags and/or features of the documentation when they aren't relevant. This is something that we'll continue doing throughout the rest of the article.

The Single Post Meta Manager Loader

<?php

/**
 * The Single Post Meta Manager Loader is a class that is responsible for
 * coordinating all actions and filters used throughout the plugin
 *
 * @package    SPMM
 */

/**
 * The Single Post Meta Manager Loader is a class that is responsible for
 * coordinating all actions and filters used throughout the plugin.
 *
 * This class maintains two internal collections - one for actions, one for
 * hooks - each of which are coordinated through external classes that
 * register the various hooks through this class.
 *
 * @since    1.0.0
 */
class Single_Post_Meta_Manager_Loader {

    /**
	 * A reference to the collection of actions used throughout the plugin.
	 *
	 * @access protected
	 * @var    array    $actions    The array of actions that are defined throughout the plugin.
	 */
	protected $actions;

	/**
	 * A reference to the collection of filters used throughout the plugin.
	 *
	 * @access protected
	 * @var    array    $actions    The array of filters that are defined throughout the plugin.
	 */
	protected $filters;

	/**
	 * Instantiates the plugin by setting up the data structures that will
	 * be used to maintain the actions and the filters.
	 */
	public function __construct() {

		$this->actions = array();
		$this->filters = array();

	}

	/**
	 * Registers the actions with WordPress and the respective objects and
	 * their methods.
	 *
	 * @param  string    $hook        The name of the WordPress hook to which we're registering a callback.
	 * @param  object    $component   The object that contains the method to be called when the hook is fired.
	 * @param  string    $callback    The function that resides on the specified component.
	 */
	public function add_action( $hook, $component, $callback ) {
		$this->actions = $this->add( $this->actions, $hook, $component, $callback );
	}

	/**
	 * Registers the filters with WordPress and the respective objects and
	 * their methods.
	 *
	 * @param  string    $hook        The name of the WordPress hook to which we're registering a callback.
	 * @param  object    $component   The object that contains the method to be called when the hook is fired.
	 * @param  string    $callback    The function that resides on the specified component.
	 */
	public function add_filter( $hook, $component, $callback ) {
		$this->filters = $this->add( $this->filters, $hook, $component, $callback );
	}

	/**
	 * Registers the filters with WordPress and the respective objects and
	 * their methods.
	 *
	 * @access private
	 *
	 * @param  array     $hooks       The collection of existing hooks to add to the collection of hooks.
	 * @param  string    $hook        The name of the WordPress hook to which we're registering a callback.
	 * @param  object    $component   The object that contains the method to be called when the hook is fired.
	 * @param  string    $callback    The function that resides on the specified component.
	 *
	 * @return array                  The collection of hooks that are registered with WordPress via this class.
	 */
	private function add( $hooks, $hook, $component, $callback ) {

		$hooks[] = array(
			'hook'      => $hook,
			'component' => $component,
			'callback'  => $callback
		);

		return $hooks;

	}

	/**
	 * Registers all of the defined filters and actions with WordPress.
	 */
	public function run() {

		 foreach ( $this->filters as $hook ) {
			 add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ) );
		 }

		 foreach ( $this->actions as $hook ) {
			 add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ) );
		 }

	}

}

Notice that this class is more of less a core component of the plugin in that it coordinates all of the actions and the filters used throughout the plugin. This plugin centralizes all of the registration and coordination of the hooks that are used throughout the plugin.

Finally, when run is called, all of the hooks are registered with WordPress so as the plugin fires, it will call each of the registered actions and filters.

The admin Directory

At this point, we're ready to turn our attention to the files located in the admin directory of the plugin. 

Though the file consists of a couple of PHP files, it also consists of a CSS file. For the purpose of this article, we are not going to be documenting the the CSS files; however, the WordPress Codex does define documentation for this.

For now, though, let's continue documenting the classes and files that exist in the admin directory.

Single Post Meta Manager Admin

The Single Post Meta Manager Admin class has a single responsibility: define the functionality to render the meta box and its styles for the dashboard.

<?php

/**
 * The Single Post Meta Manager Admin defines all functionality for the dashboard
 * of the plugin
 *
 * @package SPMM
 */

/**
 * The Single Post Meta Manager Admin defines all functionality for the dashboard
 * of the plugin.
 *
 * This class defines the meta box used to display the post meta data and registers
 * the style sheet responsible for styling the content of the meta box.
 *
 * @since    1.0.0
 */
class Single_Post_Meta_Manager_Admin {

    /**
	 * A reference to the version of the plugin that is passed to this class from the caller.
	 *
	 * @access private
	 * @var    string    $version    The current version of the plugin.
	 */
	private $version;

	/**
	 * Initializes this class and stores the current version of this plugin.
	 *
	 * @param    string    $version    The current version of this plugin.
	 */
	public function __construct( $version ) {
		$this->version = $version;
	}

	/**
	 * Enqueues the style sheet responsible for styling the contents of this
	 * meta box.
	 */
	public function enqueue_styles() {

		wp_enqueue_style(
			'single-post-meta-manager-admin',
			plugin_dir_url( __FILE__ ) . 'css/single-post-meta-manager-admin.css',
			array(),
			$this->version,
			FALSE
		);

	}

	/**
	 * Registers the meta box that will be used to display all of the post meta data
	 * associated with the current post.
	 */
	public function add_meta_box() {

		add_meta_box(
			'single-post-meta-manager-admin',
			'Single Post Meta Manager',
			array( $this, 'render_meta_box' ),
			'post',
			'normal',
			'core'
		);

	}

	/**
	 * Requires the file that is used to display the user interface of the post meta box.
	 */
	public function render_meta_box() {
		require_once plugin_dir_path( __FILE__ ) . 'partials/single-post-meta-manager.php';
	}

}

Notice that the class above has very few functional details. Primarily, the class maintains a reference to the version of the plugin, the style sheet used to style the meta box, and the function required to actually render the meta box.

Recall that all of this is setup within the core plugin file and the loader. This helps de-couple the logic that exists within the plugin so each class can focus on what its primary purpose.

Of course, the final piece of the plugin relies on the actual partial file that contains the markup necessary to display the meta box.

Single Post Meta Manager Partial

<?php
/**
 * Displays the user interface for the Single Post Meta Manager meta box.
 *
 * This is a partial template that is included by the Single Post Meta Manager
 * Admin class that is used to display all of the information that is related
 * to the post meta data for the given post.
 *
 * @package    SPMM
 */
?>
<div id="single-post-meta-manager">

    <?php $post_meta = get_post_meta( get_the_ID() ); ?>
	<table id="single-post-meta-manager-data">
	<?php foreach ( $post_meta as $post_meta_key => $post_meta_value ) { ?>
		<tr>
			<td class="key"><?php echo $post_meta_key; ?></td>
			<td class="value"><?php print_r( $post_meta_value[0] ); ?></td>
		</tr>
	<?php } ?>
	</table>

</div><!-- #single-post-meta-manager -->

This should be relatively self-explanatory; however, to be complete, note that this file takes the current post ID (through the use of the get_the_ID() function), reads the post meta data, and then iterates through it building a table that displays the keys and the values.

Finalizing The Plugin

At this point, we've completed the implementation of our plugin. From putting the object-oriented programming programming practices into place, to documenting the code.

You can grab the final version of the plugin on GitHub; however, we will be continuing our object-oriented discussion over a few more posts so that we can explore a few more advanced topics such as inheritance, abstraction, and other topics.

In the meantime, if you have questions or comments about the plugin, don't hesitate to leave them in the comments!

Advertisement