[How-To] Using Plugins for Automatic Template Edits
by
03 Jul 2007
Using Plugins for Automatic Template Edits Would you like to do make template edits without having to edit a template? Ever wondered how other mods can seem to make changes without you having to edit a single template? The answer is vBulletin's plugin system. Before we go on you should be familiar with how to edit a template, how templates work and the basics of the the plugin system. There are other tutorials that explain these concepts, if you are new to this, please take some time to learn this stuff first - it will make it much easier to understand the concepts I'm about to present. You can find other tutorials here: How to include a custom template via plugins by Kerry-Anne Template editing - by Toolblast Template mod FAQ - by Sephiroth You should also browse other tutorials in the articles section if you need to fill gaps in your knowledge. You'll also need a very basic understanding of http://devzone.zend.com/node/view/id/625, but if you are new to this - don't worry you can pick it up as you go along. I've made this tutorial much easier than most others. So if you are beginner, or never tried making your own mod, please try to follow. Right, let's begin. How does the template thing work? When your page loads from the server, PHP runs through the file, changing https://en.wikipedia.org/wiki/Variable and getting certain data ready before presenting it to your web browser. Take a look through one of those files. Let's take a look inside online.php. Do a text search for "fetch_template" and see how many times you can see this appear in the file. You'll notice that this file is loading several templates. Take a look right at the end of the file and you'll see the last template is loaded like this: Code:
eval('print_output("' . fetch_template('WHOSONLINE') . '");'); Code:
($hook = vBulletinHook::fetch_hook('online_complete')) ? eval($hook) : false; Using code executed at hooks to dynamically change the template When we change templates with the plugin system there are many hooks we can use to do this - we just need to use a hook that is called somewhere before our template is processed. Choosing the right hook depends on what you are trying to do or what the rest of your mod is doing, but generally try to use a hook as close as possible to the point where your template loads. For example, if we want to change something in WHOSONLINE, what would the point be of using a hook like global_start? That would change our template every single time a page (every page, not necessarily the who's online page) is loaded on your forum. It would be more efficient to only run the code that changes the template when we are running a page that actually needs to load the template. For this reason we will be using a hook in online.php, namely online_complete. For our example, first let's decide what we want to change in the template WHOSONLINE. Let's load the template and think of something that we want to change in that template. Adding to the template - finding our replacement point We are going to make a fairly lame hack here. We are going to display the username of the currently logged on user above the who's online table. So we need to insert our new code above that table, so let's find where this table starts. Code:
<table class="tborder" cellpadding="$stylevar[cellpadding]" cellspacing="$stylevar[cellspacing]" border="0" width="100%" align="center" id="woltable"> Now remember that our template is a giant string, and we want to insert our changes into this string. How will we do this? The answer is a common php function called http://www.php.net/str_replace. This function searches for something and replaces it with something else. All we need to do is find something within our template which is unique and easy to search for. We then replace it with our new stuff and put the old stuff back in for good measure - this means we have effectively inserted something. It's a bit like if you had a word processor document containing the sentence "The quick fox". If we wanted to insert "brown" between quick and fox we could search for "fox" and replace it with "brown fox". Our text would then read "The quick brown fox". Inserting our sample template changes We apply exactly the same principle to our template. The code we want to insert in this example looks like this: Code:
$bbuserinfo[username] Code:
$currentuser = $vbulletin->userinfo['username']; $replace = '$currentuser'; I recommend you quickly review this tutorial by Psionic Vision about variables in vBulletin. As you read it, bear in mind that you can't use the variables in this form inside the template itself, but you can use them from inside your plugin. We'll learn more about why this is in other lessons, but for now, use the technique I've described above. Creating our plugin We'll make this code a little a larger than we normally would, in order to make it easier to understand. Let's create our new plugin at the online_complete hook. We'll built it line by line, with explanations along the way. If you don't know what I'm talking about at this stage go into AdminCP -> Plugins & Products -> Plugin Manager -> (scroll to the bottom) Add New Plugin. Code:
$find = '<table class=\"tborder\" cellpadding=\"$stylevar[cellpadding]\" cellspacing=\"$stylevar[cellspacing]\" border=\"0\" width=\"100%\" align=\"center\" id=\"woltable\">'; Let's get to our next line: Code:
$currentuser = $vbulletin->userinfo['username']; $replace = '$currentuser'; Getting down to business - str_replace() Now we've defined what we are looking for and what we want to insert. Let's get down to business: Code:
$vbulletin->templatecache['WHOSONLINE'] = str_replace($find, $replace . $find, $vbulletin->templatecache['WHOSONLINE']); That's basically it - here's the code for our plugin: Code:
$find = '<table class=\"tborder\" cellpadding=\"$stylevar[cellpadding]\" cellspacing=\"$stylevar[cellspacing]\" border=\"0\" width=\"100%\" align=\"center\" id=\"woltable\">'; $currentuser = $vbulletin->userinfo['username']; $replace = '$currentuser'; $vbulletin->templatecache['WHOSONLINE'] = str_replace($find, $replace . $find, $vbulletin->templatecache['WHOSONLINE']); Things to watch out for and other limitations This has been a simple example. There are some more complexities, the biggest of which is that the https://en.wikipedia.org/wiki/Conditional_statement statements in templates can't be easily replaced with this method and that any "special" variables won't work. They can be made to work, but how to do so will be the subject of a future tutorial. Now that you know the technique, you need to bear the following in mind:
Not using conditionals inside the template might be a bit limiting for you, but consider the following point. If you want something to appear based on a certain condition, why not change it around a little bit and don't make your template replacement unless that condition is met inside your plugin? This will effectively give you the same functionality, but testing for the conditional in your plugin is simpler. Here's an example: Let's say you were going to do something like this with your template (insert the first part in front of the second, existing part): Code:
<if condition="$foo">Here is our mod!</if><div>Existing template data</div> Code:
If ($foo) { $vbulletin->templatecache['yourtemplate'] = str_replace("<div>Existing template data</div>", "Here is our mod!<div>Existing template data</div>", $vbulletin->templatecache['yourtemplate']); } It doesn't work - what now? What if it doesn't work?
What's next? You know the basics, but what to do about more complex cases? You can check out a much more indepth look at the this subject in the advanced tutorial. How about tricks and tips for debugging when it doesn't work? Check out my debugging tutorial. I encourage you to try this out for yourself and become comfortable with the technique. Do you have any older mods that required manual template edits? Why not revert those manual edits and try and make a plugin which does those edits automatically. If you succeed - share your plugin with the original mod author - I'm sure they will appreciate it. Have you tried this technique successfully? Share your examples on this thread - more examples will make it easier for others to understand. Got a tricky example that you just can't get to work? Post it (after thoroughly trying to debug it yourself). I've written this tutorial because I couldn't find this information when I was learning. If this tutorial has helped you, then share what you've learned to help others. |