# Gossamer Links Help

Table of Contents

Links SQL Developers Guide: Sample Plugin

Sample Plugin - Search Cache
In this sample, we will develop a sample plugin so you can see the full process from Start to End. It's recommended you open a new browser window with the plugin wizard and follow along. The plugin wizard will create a template for you to use to start your plugin.

We are going to add a search cache to Gossamer Links, so that when a user searches the database, their results will stay cached. The next time a search for the same term is done, the results will be retrieved from cache without nearly the overhead.

Step 1: Naming your plugin
You will be prompted to give your plugin a name. The name of your plugin corresponds to the package space it will run under, so it must conform to perls syntax. It should be only letters and numbers, and must not contain spaces. Our sample plugin is called 'SearchCache'. Convention dictates that you start with a capital letter. All code will run under the package Plugins::SearchCache. Enter in SearchCache in the name of the plugin and hit Create.

Create new plugin named: |

Step 2: Meta Information
The next step is to edit meta information about your plugin. This contains information about your plugin that will be used by Gossamer Links when users install it. You must enter at a minimum a Version Number, but should fill out all the fields completely.

It's very important to update the version number when you make changes. When users download plugins, they are presented with the version number, and from that can decide if they want to upgrade an existing installation.

To start, we'll enter:

Version: |
Author: |
URL: |
License: |
Links SQL Version Required: |
Description: | This plugin will cache search results and speed up searches on similiar topics.

and hit next. This information will now be saved with your plugin.

Step3: Hooking into Links SQL
Next we need to hook into Gossamer Links. We need to interact with Gossamer Links's search engine. There are a lot of hooks in Gossamer Links, and the plugin system gives you access to any of them. You can tell Gossamer Links to run your code before or after the normal function, and it can override the existing functions.

We decide that we will need two hooks. One before the search, and one after the search. The one before the search will look at what the user is searching for, and if it's in the cache, the plugin will return those results, and tell Gossamer Links it doesn't need to do the search. If it's not in the cache, it will tell Gossamer Links to continue on.

We also need a hook after the search, and if our cache wasn't used, let's save the results. On the hooks screen, you need the name of the hook, whether it's a pre or post hook, and what function to run. Remember, your function must be in the package Plugins::SearchCache::. In this case, I named the pre one query_cached, and the post one, log_query. You will need to add it in twice. Once done it should look like:

Hook | Type | Code
search_results | PRE | Plugins::SearchCache::query_cached
search_results | POST | Plugins::SearchCache::log_query

Step 4: Admin Menu
We don't have an admin menu for this plugin, so we will skip this step. This would normally provide the plugin author to give the user a link in the admin screen for any admin functions that are required.

Step 5: User Options
User options are variables you can have the plugin user fill out and access in your plugin. We won't do any for this, but maybe for the next version we will add a user option for how long the cache should last.

Step 6: Included Files
Every plugin needs at least an Install.pm and a ModuleName.pm (in our case SearchCache.pm). The plugin wizard will automatically generate these two files for you. It is quite common to need to bundle other files though, from images, to user cgi. From here you can upload those files that you need and the plugin wizard will bundle it in your plugin and create the install function for you.

We don't need any extra files for the SearchCache, so we hit next.

Step 7: Install Messages
The last step is too add an install and uninstall message. This should explain to the user what the plugin will do exactly during the install and uninstall: i.e. what tables it will create, what files it will install, etc.

We also need to add any custom install and uninstall code. The Wizard takes care of hooking into Gossamer Links, but we need to provide code to create our SearchCache table, and to remove the SearchCache table when we are done. Fill in the form with the following information:

Install Message | The SearchCache plugin will create a new table SearchCache that logs all queries that get run.
UnInstall Message | Removing the SearchCache plugin will erase all saved queries, but will not harm your Gossamer Links installation.

Install Code

my $c = $DB->creator('SearchCache'); my $error; $c->cols ( keyword => { pos => 1, type => 'CHAR', size => '255', not_null => 1 }, results => { pos => 2, type => 'TEXT' } ); $c->pk ('keyword'); if (! $c->create()) { $GT::SQL::errcode ||= ''; #silence -w warning. $GT::SQL::errcode eq 'TBLEXISTS' ? ($error = "Could not create table SearchLog (table already exists)\n") : ($error = "Could not create table SearchLog: $GT::SQL::error)"); $c->set_defaults(); $c->save_schema(); };

Uninstall Message | my $e = $DB->editor('SearchCache'); $e->drop_table();

You are now all done! Hit Next and the plugin wizard will create the plugin template for you. It has automatically generated an Install.pm file and a SearchCache.pm file for you. The Install file should be pretty much complete, so all you have left to do is edit the SearchCache.pm file.

Click on the Plugin Editor to finish the job!

Step 9: Insert your code
Now you should see a screen that looks something like:

Plugin Details
Plugin: | SearchCache
Version: | 0.01
Author: | Alex Krohn
License: | Freeware
Description: | This plugin will cache search results and speed up searches on similiar topics.
Plugin Files
Install.pm (3366 bytes) | Edit | Perl Check
SearchCache.pm (507 bytes) | Edit | Perl Check

Now we need to add our code for the Search Caching. Click on Edit for SearchCache.pm and enter:

# ================================================================== # Plugins::SearchCache - Auto Generated Install Module # # Plugins::SearchCache # Author : Alex Krohn # Version : 0.01 # Updated : Tue Nov 14 21:11:57 2000 # # ================================================================== # package Plugins::SearchCache; # ================================================================== use strict; use vars qw/$CACHE/; use Links qw/$IN $DB $CFG/; use GT::Dumper; use GT::Plugins qw/STOP CONTINUE/; sub query_cached { # ------------------------------------------------------------------ # Pre search hook that will return a query if we have one. # my $args = shift; my $query = $IN->param('query'); my $db = $DB->table('SearchCache'); my $cache = $db->get ( $query ); if ($cache) { $CACHE = {}; eval "$cache->{results}"; foreach my $key (keys %$CACHE) { $args->{$key} = $CACHE->{$key}; } $args->{cached} = 1; # Signal the plugin handler not to run the main search as # we already have our results. $GT::Plugins->action ( STOP ); } return $args; } sub log_query { # ------------------------------------------------------------------ # Saves a query to the database. # my $opts = shift; # First argument is results of search. if (! $opts->{cached} and $IN->param('query')) { my $string = GT::Dumper->dump ( var => '$CACHE', data => $opts ); my $db = $DB->table ('SearchCache'); my $res = $db->insert ( { keyword => $IN->param('query'), results => $string } ); } return $opts; } 1;

Simply cut and paste the above code into the edit box, and hit update. To make sure everything is correct, you can click on Perl Check to run a syntax check on it. Try it and you should see 'SearchCache.pm syntax ok'.

A couple things to note about the code:

    package Plugins::SearchCache;

Don't forget to put your code inside the proper package or it will never work.

    use strict;

Always, always run your plugins under use strict. If you want your plugin to be mod_perl compatible, this will be essential.

    use Links qw/$IN $DB $CFG/;

This makes available several variables that will be useful to you. $IN is a GT::CGI object that has the form input, $DB is a GT::SQL object that will let you interact with the database and $CFG is the Gossamer Links configuration (note you shouldn't change anything here). Other variables that you can ask for include $USER which is the currently logged in user (a hash of the user record).

    use GT::Dumper;

This module lets you dump the contents of a perl data structure into a string. We use it to dump the current search results to a string, and then save that string to the database.

    use GT::Plugins qw/STOP CONTINUE/

This imports two constants STOP and CONTINUE. You signal the plugin manager to STOP running the existing code, or by default it will continue. You do this by calling GT::Plugins->action ( STOP );

1; | Don't forget, all module must end with a 1; or they won't be able to get require'd in properly.

The important thing to understand is how arguments are passed:

PRE Hooks: The arguments you receive are the same arguments the main code would receive. So if your hook was site_html_link (the function that displays a link), your arguments is a single hash reference of the link to display. Your hook needs to return that same argument if are continuing. If you are STOP'ing and don't want any other code to run, you should return the same thing the main code would return. For site_html_link, that would be a parsed template.

POST Hooks: Very similiar. Your input is the output of the main code, and you should return the same type of arguments. So for search_results, you get a hash reference of template tags, you need to make sure you return a hash reference as well.

To signal that you want to stop, your plugin code should run:

> GT::Plugins->action ( STOP );

This tells the plugin manager not to run any more hooks, or the main code. However, you still need to make sure you return the proper arguments.

Step 10: All Done, try it out!
Now, we are all done! Click on Plugin Manager and it should be listed as a plugin waiting to be installed. Click on Install and you should now be able to try it out!

However the SearchCache is just a very simple cache, there are still quite a few things we could do to make it better:

1. Cache the page number with the results. Right now it's broken as if you search for page 2, you will get the cached page 1. We could fix this by appending the page number requested in the keyword field.

2. Remove entries from the cache. We will want to remove old entries from the cache. This should be done periodically to make sure that cached data isn't too out of date.

3. Use GT::Cache to cache in-memory if under mod_perl. This would be an even better performance boost as no database access would be required to return matching results. GT::Cache would also limit the cache size automatically and keep the most popular ones, while removing the less frequent ones.

Maybe for version 0.02?

This just scratches the surface of what you can do, please visit the reference section, or join other plugin developers online for more information.

Table of Contents