Display Rendering * The class uses a similar technique to Ruby On Rails views, whereby the display HTML is kept * in a separate directory and file from the main code. A display is 'rendered' (sent to the browser) * or 'captured' (returned to the calling function). * * Template files are separated into two areas: admin and user. Admin templates are only for display in * the WordPress admin interface, while user templates are typically for display on the site (although neither * of these are enforced). All templates are PHP code, but are referred to without .php extension. * * The reason for this separation is that one golden rule of plugin creation is that someone will always want to change * the formatting and style of your output. Rather than forcing them to modify the plugin (bad), or modify files within * the plugin (equally bad), the class allows user templates to be overridden with files contained within the theme. * * An additional benefit is that it leads to code re-use, especially with regards to Ajax (i.e. your display code can be called from * many locations) * * Template files are located within the 'view' subdirectory of the plugins base (specified when registering the plugin): * *
myplugin/view/admin
 * myplugin/view/myplugin
* * Admin templates are contained within 'admin', and user templates are contained within a directory of the same name as the plugin. * * User files can be overridden within the theme by creating a similar directory structure: * *
/themes/mytheme/view/myplugin
* * The class will first look in the theme and then defaults to the plugin. A plugin should always provide default templates. * *

Display Parameters

* Also similar to Ruby On Rails, when you display a template you must supply the parameters that the template has access to. This tries * to ensure a very clean separation between code and display. Parameters are supplied as an associative array mapping variable name to variable value. * * For example, * * array ('message' => 'Your data was processed', 'items' => 103); * *

How it works in practice

* You create a template file to display how many items have been processed. You store this in 'view/admin/processed.php': * *
<p>You processed <?php echo $items ?> items</p>
* * When you want to display this in your plugin you use: * *
 $this->render_admin ('processed', array ('items' => 100));
 *
 * @package WordPress base library
 * @author John Godley
 * @copyright Copyright (C) John Godley
 **/

class CustomPostTemplates_Plugin
{
	/**
	 * Plugin name
	 * @var string
	 **/
	var $plugin_name;
	
	/**
	 * Plugin 'view' directory
	 * @var string Directory
	 **/
	var $plugin_base;
	
	
	/**
	 * Register your plugin with a name and base directory.  This must be called once.
	 *
	 * @param string $name Name of your plugin.  Is used to determine the plugin locale domain
	 * @param string $base Directory containing the plugin's 'view' files.
	 * @return void
	 **/
	
	function register_plugin ($name, $base)
	{
		$this->plugin_base = rtrim (dirname ($base), '/');
		$this->plugin_name = $name;

		$this->add_action ('init', 'load_locale');
	}
	
	function load_locale ()
	{
		// Here we manually fudge the plugin locale as WP doesnt allow many options
		$locale = get_locale ();
		if ( empty($locale) )
			$locale = 'en_US';

		$mofile = dirname (__FILE__)."/locale/$locale.mo";
		load_textdomain ($this->plugin_name, $mofile);
	}
	
	
	/**
	 * Register a WordPress action and map it back to the calling object
	 *
	 * @param string $action Name of the action
	 * @param string $function Function name (optional)
	 * @param int $priority WordPress priority (optional)
	 * @param int $accepted_args Number of arguments the function accepts (optional)
	 * @return void
	 **/
	
	function add_action ($action, $function = '', $priority = 10, $accepted_args = 1)
	{
		add_action ($action, array (&$this, $function == '' ? $action : $function), $priority, $accepted_args);
	}


	/**
	 * Register a WordPress filter and map it back to the calling object
	 *
	 * @param string $action Name of the action
	 * @param string $function Function name (optional)
	 * @param int $priority WordPress priority (optional)
	 * @param int $accepted_args Number of arguments the function accepts (optional)
	 * @return void
	 **/
	
	function add_filter ($filter, $function = '', $priority = 10, $accepted_args = 1)
	{
		add_filter ($filter, array (&$this, $function == '' ? $filter : $function), $priority, $accepted_args);
	}

	
	/**
	 * Register a WordPress meta box
	 *
	 * @param string $id ID for the box, also used as a function name if none is given
	 * @param string $title Title for the box
	 * @param int $page WordPress priority (optional)
	 * @param string $function Function name (optional)
	 * @param string $context e.g. 'advanced' or 'core' (optional)
	 * @param int $priority Priority, rough effect on the ordering (optional)
	 * @return void
	 **/
	
	function add_meta_box($id, $title, $function = '', $page, $context = 'advanced', $priority = 'default')
	{
		require_once( ABSPATH . 'wp-admin/includes/template.php' );
		add_meta_box( $id, $title, array( &$this, $function == '' ? $id : $function ), $page, $context, $priority );
	}

	/**
	 * Special activation function that takes into account the plugin directory
	 *
	 * @param string $pluginfile The plugin file location (i.e. __FILE__)
	 * @param string $function Optional function name, or default to 'activate'
	 * @return void
	 **/
	
	function register_activation ($pluginfile, $function = '')
	{
		add_action ('activate_'.basename (dirname ($pluginfile)).'/'.basename ($pluginfile), array (&$this, $function == '' ? 'activate' : $function));
	}
	
	
	/**
	 * Special deactivation function that takes into account the plugin directory
	 *
	 * @param string $pluginfile The plugin file location (i.e. __FILE__)
	 * @param string $function Optional function name, or default to 'deactivate'
	 * @return void
	 **/
	
	function register_deactivation ($pluginfile, $function = '')
	{
		add_action ('deactivate_'.basename (dirname ($pluginfile)).'/'.basename ($pluginfile), array (&$this, $function == '' ? 'deactivate' : $function));
	}
	
	
	/**
	 * Renders an admin section of display code
	 *
	 * @param string $ug_name Name of the admin file (without extension)
	 * @param string $array Array of variable name=>value that is available to the display code (optional)
	 * @return void
	 **/
	
	function render_admin ($ug_name, $ug_vars = array ())
	{
		global $plugin_base;
		foreach ($ug_vars AS $key => $val)
			$$key = $val;

		if (file_exists ("{$this->plugin_base}/view/admin/$ug_name.php"))
			include ("{$this->plugin_base}/view/admin/$ug_name.php");
		else
			echo "

Rendering of admin template {$this->plugin_base}/view/admin/$ug_name.php failed

"; } /** * Renders a section of user display code. The code is first checked for in the current theme display directory * before defaulting to the plugin * * @param string $ug_name Name of the admin file (without extension) * @param string $array Array of variable name=>value that is available to the display code (optional) * @return void **/ function render ($ug_name, $ug_vars = array ()) { foreach ($ug_vars AS $key => $val) $$key = $val; if (file_exists (TEMPLATEPATH."/view/{$this->plugin_name}/$ug_name.php")) include (TEMPLATEPATH."/view/{$this->plugin_name}/$ug_name.php"); else if (file_exists ("{$this->plugin_base}/view/{$this->plugin_name}/$ug_name.php")) include ("{$this->plugin_base}/view/{$this->plugin_name}/$ug_name.php"); else echo "

Rendering of template $ug_name.php failed

"; } /** * Renders a section of user display code. The code is first checked for in the current theme display directory * before defaulting to the plugin * * @param string $ug_name Name of the admin file (without extension) * @param string $array Array of variable name=>value that is available to the display code (optional) * @return void **/ function capture ($ug_name, $ug_vars = array ()) { ob_start (); $this->render ($ug_name, $ug_vars); $output = ob_get_contents (); ob_end_clean (); return $output; } /** * Captures an admin section of display code * * @param string $ug_name Name of the admin file (without extension) * @param string $array Array of variable name=>value that is available to the display code (optional) * @return string Captured code **/ function capture_admin ($ug_name, $ug_vars = array ()) { ob_start (); $this->render_admin ($ug_name, $ug_vars); $output = ob_get_contents (); ob_end_clean (); return $output; } /** * Display a standard error message (using CSS ID 'message' and classes 'fade' and 'error) * * @param string $message Message to display * @return void **/ function render_error ($message) { ?>

plugin_base; } /** * Get a URL to the plugin. Useful for specifying JS and CSS files * * For example, * * @return string URL **/ function url ($url = '') { if ($url) return str_replace ('\\', urlencode ('\\'), str_replace ('&amp', '&', str_replace ('&', '&', $url))); else { $root = ABSPATH; if (defined ('WP_PLUGIN_DIR')) $root = WP_PLUGIN_DIR; $url = substr ($this->plugin_base, strlen ($this->realpath ($root))); if (DIRECTORY_SEPARATOR != '/') $url = str_replace (DIRECTORY_SEPARATOR, '/', $url); if (defined ('WP_PLUGIN_URL')) $url = WP_PLUGIN_URL.'/'.ltrim ($url, '/'); else $url = get_bloginfo ('wpurl').'/'.ltrim ($url, '/'); // Do an SSL check - only works on Apache global $is_IIS; if (isset ($_SERVER['HTTPS']) && !$is_IIS) $url = str_replace ('http://', 'https://', $url); } return $url; } /** * Performs a version update check using an RSS feed. The function ensures that the feed is only * hit once every given number of days, and the data is cached using the WordPress Magpie library * * @param string $url URL of the RSS feed * @param int $days Number of days before next check * @return string Text to display **/ function version_update ($url, $days = 7) { if (!function_exists ('fetch_rss')) { if (!file_exists (ABSPATH.'wp-includes/rss.php')) return ''; include (ABSPATH.'wp-includes/rss.php'); } $now = time (); $checked = get_option ('plugin_urbangiraffe_rss'); // Use built-in Magpie caching if (function_exists ('fetch_rss') && (!isset ($checked[$this->plugin_name]) || $now > $checked[$this->plugin_name] + ($days * 24 * 60 * 60))) { $rss = fetch_rss ($url); if (count ($rss->items) > 0) { foreach ($rss->items AS $pos => $item) { if (isset ($checked[$this->plugin_name]) && strtotime ($item['pubdate']) < $checked[$this->plugin_name]) unset ($rss->items[$pos]); } } $checked[$this->plugin_name] = $now; update_option ('plugin_urbangiraffe_rss', $checked); return $rss; } } /** * Version of realpath that will work on systems without realpath * * @param string $path The path to canonicalize * @return string Canonicalized path **/ function realpath ($path) { if (function_exists ('realpath')) return realpath ($path); else if (DIRECTORY_SEPARATOR == '/') { $path = preg_replace ('/^~/', $_SERVER['DOCUMENT_ROOT'], $path); // canonicalize $path = explode (DIRECTORY_SEPARATOR, $path); $newpath = array (); for ($i = 0; $i < sizeof ($path); $i++) { if ($path[$i] === '' || $path[$i] === '.') continue; if ($path[$i] === '..') { array_pop ($newpath); continue; } array_push ($newpath, $path[$i]); } $finalpath = DIRECTORY_SEPARATOR.implode (DIRECTORY_SEPARATOR, $newpath); return $finalpath; } return $path; } function checked ($item, $field = '') { if ($field && is_array ($item)) { if (isset ($item[$field]) && $item[$field]) echo ' checked="checked"'; } else if (!empty ($item)) echo ' checked="checked"'; } function select ($items, $default = '') { if (count ($items) > 0) { foreach ($items AS $key => $value) { if (is_array ($value)) { echo ''; foreach ($value AS $sub => $subvalue) echo ''; echo ''; } else echo ''; } } } } if (!function_exists ('pr')) { function pr ($thing) { echo '
';
		print_r ($thing);
		echo '
'; } } if (!class_exists ('Widget_SU')) { class Widget_SU { function Widget_SU ($name, $max = 1, $id = '', $args = '') { $this->name = $name; $this->id = $id; $this->widget_max = $max; $this->args = $args; if ($this->id == '') $this->id = strtolower (preg_replace ('/[^A-Za-z]/', '-', $this->name)); $this->widget_available = 1; if ($this->widget_max > 1) { $this->widget_available = get_option ('widget_available_'.$this->id ()); if ($this->widget_available === false) $this->widget_available = 1; } add_action ('init', array (&$this, 'initialize')); } function initialize () { // Compatability functions for WP 2.1 if (!function_exists ('wp_register_sidebar_widget')) { function wp_register_sidebar_widget ($id, $name, $output_callback, $classname = '') { register_sidebar_widget($name, $output_callback, $classname); } } if (!function_exists ('wp_register_widget_control')) { function wp_register_widget_control($name, $control_callback, $width = 300, $height = 200) { register_widget_control($name, $control_callback, $width, $height); } } if (function_exists ('wp_register_sidebar_widget')) { if ($this->widget_max > 1) { add_action ('sidebar_admin_setup', array (&$this, 'setup_save')); add_action ('sidebar_admin_page', array (&$this, 'setup_display')); } $this->load_widgets (); } } function load_widgets () { for ($pos = 1; $pos <= $this->widget_max; $pos++) { wp_register_sidebar_widget ($this->id ($pos), $this->name ($pos), $pos <= $this->widget_available ? array (&$this, 'show_display') : '', $this->args (), $pos); if ($this->has_config ()) wp_register_widget_control ($this->id ($pos), $this->name ($pos), $pos <= $this->widget_available ? array (&$this, 'show_config') : '', $this->args (), $pos); } } function args () { if ($this->args) return $args; return array ('classname' => ''); } function name ($pos) { if ($this->widget_available > 1) return $this->name.' ('.$pos.')'; return $this->name; } function id ($pos = 0) { if ($pos == 0) return $this->id; return $this->id.'-'.$pos; } function show_display ($args, $number = 1) { $config = get_option ('widget_config_'.$this->id ($number)); if ($config === false) $config = array (); $this->load ($config); $this->display ($args); } function show_config ($position) { if (isset ($_POST['widget_config_save_'.$this->id ($position)])) { $data = $_POST[$this->id ()]; if (count ($data) > 0) { $newdata = array (); foreach ($data AS $item => $values) $newdata[$item] = $values[$position]; $data = $newdata; } update_option ('widget_config_'.$this->id ($position), $this->save ($data)); } $options = get_option ('widget_config_'.$this->id ($position)); if ($options === false) $options = array (); $this->config ($options, $position); echo ''; } function has_config () { return false; } function save ($data) { return array (); } function setup_save () { if (isset ($_POST['widget_setup_save_'.$this->id ()])) { $this->widget_available = intval ($_POST['widget_setup_count_'.$this->id ()]); if ($this->widget_available < 1) $this->widget_available = 1; else if ($this->widget_available > $this->widget_max) $this->widget_available = $this->widget_max; update_option ('widget_available_'.$this->id (), $this->widget_available); $this->load_widgets (); } } function config_name ($field, $pos) { return $this->id ().'['.$field.']['.$pos.']'; } function setup_display () { ?>

name ?>

id); ?>