Advanced Plugin Optimization System
by
23 Mar 2008
New! Attached prototype files to get you started Also updated to address a bug
This is a method you should use to optimize the way your plugins work in your hacks!
Background
After writing hacks with many many plugins, you run into a couple problems...- Finding a particular plugin to edit is a nightmare in the Plugin Manager
- Bad on memory, especially for sites with dozens of hacks installed
So, I just recently perfected a plugin optimization system which solves both problems very admirably, and I am converting all of my hacks to use it.
Every coder should be familiar with this clever optimization technique, it is even in the vBulletin manual: http://www.vbulletin.org/forum/showt...ghlight=plugin
Basically: move plugins to the file system! There is also a "Plugin Accelerator" which does that too.
However, now you have a couple dozen FILES to watch after, and it still is too messy for my taste. My next step was to put them all into a single file that gets included in every plugin, but the plugin also has to set some global indicator before including, because the vB system doesn't declare what plugin it is writing to the plugin code itself. It was either many files and 1 code line per plugin, or 1 file and 2 code lines per plugin. I wanted 1 file and 1 line per plugin So begins tutorial proper...
Advanced Plugin Optimization System
You should know what code is in your plugins, how they work, how to find hooks, etc - I'm not getting into that. I'm also assuming you know how to code PHP in general, and know what functions/OOP I'm talking about, and can look up any you don't.
First create the file that will house the plugin code and put it somewhere. I will use the file myhack_plugins.php in the plugins subfolder in the forum root.
Create all of your plugins in the ACP plugin manager that you would normally use, and put the exact same single line in each them:
PHP Code:
include(DIR . '/plugins/myhack_plugins.php');
Remember which hooks they use and what code you want to put in them. This optimization is best applied after creating your hack, but not necessarily. Adjust the path to whatever you named it of course. You can also use require to put up errors if the plugins file is missing, but don't use **_once functions if you have more than 1 plugin or it won't work.
Create a functions file that has this in it:
PHP Code:
class vBulletinHook_MyHack extends vBulletinHook { function vBulletinHook_MyHack(&$pluginlist, &$hookusage) { $this->pluginlist =& $pluginlist; $this->hookusage =& $hookusage; } function fetch_hook_object($hookname) { if (!isset($this->hookusage["$hookname"])) { $this->hookusage["$hookname"] = !empty($this->pluginlist["$hookname"]); } return str_replace('include(', "\$hookname = '$hookname';\r\ninclude(", strval($this->pluginlist["$hookname"])); } }
This could also be put in the plugins file itself, but then you have to deal with duplicate definition errors, so easier to then refer to the file with
PHP Code:
require_once(DIR . '/includes/functions_myhack.php');
at the top of the plugins file. Remember to change the 'myhack' everywhere to match your hack, preferably to your product identifier. Doing that will also ensure that you don't conflict with other people doing this.
Figure out which hook executes very first in your hack. The very first in vBulletin at all is init_startup, and you might want to add a plugin at that hook just to make sure the system works. Remember what your first hook is.
Now, in the plugins file, it works like this:
PHP Code:
$vbulletin = $GLOBALS['vbulletin']; $foruminfo = $GLOBALS['foruminfo']; $db = $vbulletin->db; if (!defined('VB_AREA')) { exit; } require_once(DIR . '/includes/functions_myhack.php'); switch (strval($hookname) { case 'some_hook_name': { //code that runs at this hook } break; case 'someother_hook_name': { //code that runs at this hook } break; //and so on, one per plugin doing that default: { //code that runs at the very first hook determined above $hookobj =& vBulletinHook::init(); $hookobj = new vBulletinHook_MyHack($hookobj->pluginlist, $hookobj->hookusage); } break; }
That's it! Keep in mind your names and paths of course. The way it works is that it picks out which hook is executing in a big switch statement, with each entry its own plugin code. However the name of the hook is only reported by extending the vBulletinHook class, so the very first hook executed not only won't have the hookname reported (which is why it is in the default block) but it should also be the place where you extend the vBulletinHook class to begin reporting the hookname for all the rest. Note that at the top the only important lines are the $hookobj line and the require_once line, but the other lines are a good example of what you can do for ALL plugins, such as globalizing $vbulletin and checking for illegal loading of the file by itself with VB_AREA. Use and expand as you see fit (but some sort of acknowledgement would be awesome)
Benefits- As optimized of a plugin system as possible - 1 line per plugin and 1 file for code
- You can work on all plugins at once in your favorite code editor
- Plugins can be easily encrypted in their single file
- Works on ALL 3.6.x through 3.7.x without ANY end-user file edits (3.5.x untested)
- Code applicable to all plugins can be done once at the top of the plugins file
- Include the plugins file with any other files for your hack
- Won't interfere with other hacks that use this or other systems, or regular vB
- You and others only edit and replace that one file
- Works on all plugin types even within functions and classes
- Allows you to write plugins that define functions and use the return command!
Demo
You can see this optimization system in use in my vBCredits 1.4rc2 hack here or here. The older version of this (not quite as good, but what I was doing before perfecting this system) is in use in my vBTracker LITE hack here.
|