Templates and Shortcodes in a plugin

From e107 Wiki
Jump to: navigation, search

e107 Wiki: English | Русский | Deutsch | Français | Magyar | Português | Български | Česky | Nederlands | Ελληνικά | Italiano | Norske | Polska | Slovenščina | Español | Svenska | Translate: Wiki | Page

logo_wiki.png

Current Release 1.0.4 | e107.org | Download | Changelog | Forum | Plugins | Themes | RSS Feed of Latest Changes | Atom Feed of Latest Changes


How to write a plugin
Main page > I : First Aid > II : Development > III : Administration > IV : How To's > V : Plugin Writing > VI : Theming & Shortcodes



Contents

Introduction

If your plugin is anything more than simple then there are some good reasons why you should consider using templates and shortcodes in your plugin.

First, it helps separate the logic in your code that generates the data to be displayed from the way the data is displayed. This in turn allows you to redesign the layout without touching (or breaking) your logic code. Of course, it also allow you to change the logic (as long as the same data is generated) to fix bugs, be more efficient. etc. without the layout of the data getting in the way.

Secondly, it allows you to provide a means for website administrators or other designers to create new templates for your plugin. This, for example, allows them to present your data in a different way or makes it fit better with their specific theme.

Other benefits include ease of ongoing maintentace and addition of new features.

This article describes the use of templates and shortcodes much as the Content Management plugin uses them. It doesn't have quite the same level of complexity, but should give you a good overview of how you can incorporate these ideas into your own plugin.

What's Required

In your plugin code there are two basic steps:

  • generate all the data to be displayed.
This may involve reading a database, checking preferences or user classes, calculations, etc.. At this stage, no consideration to the page layout is required.
  • parse the template, replacing shortcodes with data values
This is easier than it sounds, as it's simply a call to the parseTemplate() function of the e_Parse class.

To allow the parsing to work correctly, a template and the shortcodes must be defined.

The template is just a string that defines the HTML to be generated for the page with placeholders where the data should be displayed - these placeholders are the shortcodes.

In addition, shortcodes offer an additional feature that allows the result to be prefixed/suffixed with HTML code. This feature is shown in the example but described in more detail in the Shortcodes Formatting article.

Note: to make the data visible to the shortcode it must be in the global scope.

Plugin Code

This is an example of the code you'd put in your main plugin code.

Code: myplugin.php snippet
include(e_PLUGIN."myplugin/myplugin_shortcodes.php");
include(e_PLUGIN."myplugin/templates/myplugin_default.php");

    // Read one row from the database
    $sql->db_Select("user", "*", "");
	
    $myplugindata = $sql->db_Fetch();
    // The data is placed in to cachevars() so that the shortcode can access it.
    cachevars('myplugin_current_data', $myplugindata);

    // Parse the template to put the values eg. {MYSHORTCODE}, into the HTML.
    $text = $tp->parseTemplate( $MYPLUGIN_TEMPLATE, FALSE, $myplugin_shortcodes);

    echo $text;	

In the call to parseTemplate:

  • $MYPLUGIN_TEMPLATE is the template string defined in the template file
  • FALSE indicates that core shortcodes should not be translated, set this to TRUE if core shortcodes are being used in the template.
  • $myplugin_shortcodes is the variable containing the shortcodes, defined in the shortcode file.

Template Code

By convention, the plugin templates are stored in a different file to the main plugin. This keeps them separate and makes the main source file (responsible for the data and logic) less cluttered. This example also shows how to use shortcode formatting techniques.

Code: myplugin_default.php
<?php 
global $sc_style;

$sc_style['MYPLUGIN_USER_NAME']['pre'] = "<td>";
$sc_style['MYPLUGIN_USER_NAME']['post'] = "</td>";

$sc_style['MYPLUGIN_USER_LOGIN']['pre'] = "<td>";
$sc_style['MYPLUGIN_USER_LOGIN']['post'] = "</td>";

$sc_style['MYPLUGIN_USER_EMAIL']['pre'] = "<td>";
$sc_style['MYPLUGIN_USER_EMAIL']['post'] = "</td>";

$MYPLUGIN_TEMPLATE = "
<table>
   <tr>
      {MYPLUGIN_USER_NAME}
      {MYPLUGIN_USER_LOGIN}
      {MYPLUGIN_USER_EMAIL}
   </tr>
</table>
";
?>

In this code, each shortcode is delimited by curly brackets (e.g. {MYPLUGIN_USER_NAME}). This is required as this is what the parsing routine uses to identify shortcodes.

Note: this example isn't perfect. The idea of using the $sc_style array to generate the opening and closing table cell tags is fine in principle; if there is no data for a field (e.g. User Name) then no tags will be generated, which is what we want. However, in this example if none of the three fields have data then there will be no cell tags and invalid HTML will be generated. Exactly how the $sc_style array is used will be dependent on your data and what you need to happend when a piece of data is present or not.

Shortcode Code

Finally, we define our shortcodes. Again, these are in their own file, which allows multiple templates to use the same shortcodes simply by including the file.

Code: myplugin_shortcodes.php
<?php 
if (!defined('e107_INIT')) { exit; }
include_once(e_HANDLER.'shortcode_handler.php');
global $tp;
$myplugin_shortcodes = $tp->e_sc->parse_scbatch(__FILE__);

/*

// ------------------------------------------------
SC_BEGIN MYPLUGIN_USER_NAME
   $item = getcachedvars('myplugin_current_data');
   return $item["user_name"];
SC_END

// ------------------------------------------------
SC_BEGIN MYPLUGIN_USER_LOGIN
   $item = getcachedvars('myplugin_current_data');
   return $item["user_login"];
SC_END

// ------------------------------------------------
SC_BEGIN MYPLUGIN_USER_EMAIL
   $item = getcachedvars('myplugin_current_data');
   return $item["user_email"];
SC_END

*/
?>

This code looks a bit strange as the main part of it appears to be commented out. In fact, it is and this is intentional. What happens is, when the file is included, the first few line read in the file and find all the shortcodes, which are denoted by SC_BEGIN and SC_END. The shortcodes are then stored in $myplugin_shortcodes. The plugin writer does not need to worry about this; just include the first few lines as above and all will be well.

For each shortcode, you write whatever PHP you need to generate the undecorated data (i.e. the shortcode does not generate layout HTML). Your data must be available to the shortcode. The most efficient way to make the data available to the shortcode is to use cachevars($id, $var) and getcachedvars($id). Each shortcode returns a string at the end which is the data value. If you treat the SC_BEGIN and SC_END tags like the start and end of a PHP function you shouldn't go wrong with respect to the scope of data you are accessing.

Adding Parameters to Shortcodes

It is possible to extend your shortcodes with parameter values. The parameters are passed to your code in the global $parm variable.

There's no hard and fast rule as to the format of the shortcode parameters as it's up to the plugin writer to handle whatever comes through. Here are a couple of examples of how parameters can be used:

Code: myplugin_default.php snippet
$MYPLUGIN_TEMPLATE = "
<table>
   <tr>
      {MYPLUGIN_USER_NAME=label}
      {MYPLUGIN_USER_LOGIN=label&link=true}
   </tr>
</table>
";
Code: myplugin_shortcodes.php snippet
// ------------------------------------------------
SC_BEGIN MYPLUGIN_USER_NAME
   global $myplugindata;

   $text = "";

   // Check parameter to see if a label is required
   if ($parm == "label") {
      $text .= "User name:";
   }
   $text .= $myplugindata["user_name"];
   return $text;
SC_END

// ------------------------------------------------
SC_BEGIN MYPLUGIN_USER_LOGIN
   global $myplugindata;

   // Convert parameters in to an array
   parse_str($parm, $parms);

   $text = "";

   // Check to see if we want a label
   if (array_key_exists("label", $parms)) {
      $text .= "E-Mail address: ";
   } 

   // Check to see if we should make the e-mail address a link
   if ($parms["link"] == "true") {
      $text .= "<a href='mailto:".$myplugindata["user_login"]."'>";
      $text .= $myplugindata["user_login"].'</a>';
   } else {
      $text .= $myplugindata["user_login"];
   }
   return $text;
SC_END

*/
?>

Extending Shortcode files

You can extend an existing shortcode file with another file of shortcodes. For instance, suppose you created a new shortcode file in your theme directory and you want to extend your existing myplugin_shortcodes.php file or override some of these shortcodes. Add the following line to the top of your myplugin_shortcodes.php file:

Code: myplugin_shortcodes.php
//Add to top of myplugin_shortcodes.php 
$myplugin_shortcodes = array_merge ($myplugin_shortcodes, $tp -> e_sc -> parse_scbatch(THEME."more_shortcodes.php"));

where more_shortcodes.php is the name of your new shortcode file.