Archive

You are currently browsing the archives for the Work category.

Oct

19

Drupal like templating for your wordpress plugin

By mike@mike-miles.com

As part of my job, from time to time I am responsible for building custom WordPress plugins for client sites. One of the biggest pains of building a plugin (besides the miss-mash of resources/tutorials on how to build one) is theming the output. Weather it be output to the front end user, or an admin screen or a form, I have never been able to find a great way to separate back end code and front end code (not having HTML within the plugin itself). That is until the idea came to me to mimic the method Drupal uses to template output (I do a lot more Drupal development, than I do wordpress). On the latest wordpress plugin I had to develop, I decided to implement my idea and it worked quite well. so I thought I’d share the methods used so that any other wordpress plugin developer out there might use it.

A quick basic overview of how Drupal templates content for any of you who maybe unfamiliar. When a Drupal module (module is to Drupal, what plugin is to WordPress) want to output content it calls a theming function, an example:

<?php
//... other module code
return theme('my-template-file',$arg1,$arg2);
?>

So basically, you call a function ( called ‘theme’) and pass it the name of the template file you want to use along with the arguments to pass to that template. (This is a very basic overview of how the Drupal theme function works).

What Drupal then does is start an output buffer, render the content of the template (passing the arguments as variables in the local scope) captures the output, clears the output buffer and return the rendered content. here is the function that does it (from ‘theme.inc’ in the Drupal directory ‘includes’).

<?php
function theme_render_template($template_file, $variables) {
	extract($variables, EXTR_SKIP);  // Extract the variables to a local namespace
	ob_start();                      // Start output buffering
	include "./$template_file";      // Include the template file
	$contents = ob_get_contents();   // Get the contents of the buffer
	ob_end_clean();                  // End buffering and discard
	return $contents;                // Return the contents
}
?>

So we want to replicate this function in our WordPress plugin, all be it with a few additions. First, we’ll need to be able to get the location of our plugin, and thus the full location of the template file (Drupal does something similar with themes and modules in other functions to get the full $template_file path). Second, we’ll want to extend the functionality of this to allow multiple templates to be used. This is again, modeled after Drupal. What the Drupal theme engine allows you to do is have different versions of a template file. For instance, there will be a basic one with the module, but any theme can also have the same template file which will be used instead (This allows Drupal sites to customize output without needing to alter the modules core code).

So our WordPress plugin function will look something like this:

<?php
//... other module code
function myplugin_theme($template,$variables){
        //empty content to start
	$contents = '';
	//no template path to start
	$template_file = false;
	//get the path or the current active theme
	$theme_path = get_stylesheet_directory();
	//get the path to our plugin template directory
	$plugin_path = dirname(__FILE__).'/templates/';
	//assume the template name we are given does not have the extension
	$template.='.tpl.php';
	//see which template file we want to use
	//doe the theme have the template file?
	if (file_exists($theme_path.'/'.$template)){
		//it does, so use this as the path
		$template_file = $theme_path.'/'.$template;
		//does the plugin have the template file?
	}else if (file_exists($plugin_path.$template)){
		//it does, use that instead
		$template_file = $plugin_path.$template;
	} // else, there is no template file found.
	//do we have a template file to output?
	if ($template_file){
		extract($variables, EXTR_SKIP);  // Extract the variables to a local namespace
		ob_start();                      // Start output buffering
		include "./$template_file";      // Include the template file
		$contents = ob_get_contents();   // Get the contents of the buffer
		ob_end_clean();                  // End buffering and discard
	}
	return $contents;                // Return the contents
}
?>

A quick break down of our function and how it work. The function retrieves the current active theme path, as well as the path to our plugin. It first checks to see if the theme has the template file (indicates the theme creator has specialized the output of this template), else it sees if the plugin has a base template file (as it should). If there is a template file, then the function uses the PHP extract function to move the variables passed into the local namespace. It then does the same thing as the Drupal function, renders the content and returns it. Not that, if the template file is not found our function returns an empty string.

So how might one use this? Well here is an example, say our module displays a list of restaurants near a users location. We don’t know how many results are being returned, but we want to template how the list looks. so we might do something like this:

<?php
function mymodule_display_restaurants(){
	//User submitted their zipcode via a form
	$zipcode = $_POST['zipcode'];
	//we retrieve a list of restaurants near the users zipcode
	$restaurants = mymodule_get_restaurants($zipcode);
	//display restaurants to user
	echo mymodule_theme('restaurant-list',array('restaurants'=>$restaurants));
}
?>

What is happening here is the function ‘mymodule_display_restaurants’ is sending an array of restaurants to the template file ‘restaurant-list.tpl.php’. Here is an example of what that template file might look like:

<div id="restaurant-list">
<?php if (sizeof($restaurants)>0){ ?>
	<p>Here are the restaurants in your area</p>
	<ul>
	<?php foreach ($restaurants as $restaurant){ ?>
		<li><?php echo $restaurant->title; ?> - <?php echo $restaurant->address; ?></li>
	<?php } ?>
	</ul>
<?php }else{ ?>
	<p>It looks like there are no restaurants in your area.</p>
<?php } ?>
</div>

There is still PHP in our template file, but what is most important is that the HTML to display this list is separated from our plugin code. This means that a theme developer could create a custom template for our plugin to display this data differently (say in a table).

This system also allows you to build complex themed output, theming individual parts with separate template files and theming all the output in a template. Example, we might change our previous function to something like this to make it more flexible:

<?php
function mymodule_display_resturants(){
	//User submitted their zipcode via a form
	$zipcode = $_POST['zipcode'];
	//we retrieve a list of resturnats near the usrs zipcode
	$resturants = mymodule_get_resturants($zipcode);
	if (sizeof($resturants)>0){
		foreach ($resturants as &$resturant){
			$resturant = mymodule_theme('resturant',array('resturant'=>$resturant));
		}
	}
	//display resturants to user
	echo mymodule_theme('resturant-list',array('resturants'=>$resturants));
}
?>

The ‘restaurant.tpl.php’, might look something like this:

<div>
        <strong>Name:</strong><?php echo $resturant->title; ?><br />
	<strong>Address:</strong><?php echo $resturant->address; ?><br />
</div>

And our ‘restaurant-list.tpl.php’ will now look something like this:

<div id="restaurant-list">
<?php if (sizeof($restaurants)>0){ ?>
	<p>Here are the restaurants in your area</p>
	<?php
		foreach ($restaurants as $restaurant){
			echo $restaurant;
		}
	?>
<?php }else{ ?>
        <p>It looks like there are no restaurants in your area.</p>
<?php } ?>
</div>

So you can see, this gives themers much more control over the output of your plugins data without needing to alter your plugin.

 

I hope this post proves useful and your able to build upon and use this theming convention to make your plugin development much more flexible.

 

 

 

Oct

24

Genuine Labs: the Augmented Reality Business card

By mike@mike-miles.com

I’ve said this before, and I’ll say it again, I love my job and where I work (Genuine Interactive).  It’s an enviroment that fosters hard work, creativity and great results.  It’s also a place where the guys in charge have made it clear that everyone can chime in and express their ideas for projects.

A few months ago I did just that.  I was talking to Chris Pape, and I asked him if any of our flash developers had experience with augmented reality.  I told him I had an idea I wanted to try, making an augmented reality business card where our company logo was the symbol.  He thought it was a great idea, and told me it was something he’d love to look into.

Read more »