# Plugin Development

- Overview
- Functions for writing Plugins
  - Moderation Functions
  - Admin and User Menu Functions
  - Search Functions
  - Comment Functions
  - Stats Function
  - Uninstall Function
  - User Functions
  - Profile Functions
  - Misc. Functions
- Implementing your Admin Interface
- Preparing your Geeklog Plugin Distribution
- How To Install A Geeklog Plugin
- Deliver Your Plugin!
- Description of the Geeklog Plugin API
  - Moderation Functions
  - Admin and User Functions
  - Search Functions
  - Stats Functions

## Overview

Geeklog is becoming more and more popular each day and we, the Geeklog developers, are amazed at some of the great hacks people have made to extend their Geeklog installation to fit their own needs. At the same time, the Geeklog development team is continually adding new features that make Geeklog even better. We have realized the need for Geeklog to support two threads of development: core geeklog code and plugin-code. By building in the infrastructure needed to extend Geeklog's functionality through plugins we can make a clean seperation between the Geeklog codebase and plugin code so that we can concentrate on making Geeklog's core code better while others can develop plugins so that Geeklog fits their needs. With that said, Geeklog now has a Plugin application program interface (API).

At the highest level, the Geeklog Plugin API is generic code that is called in strategic places in the Geeklog codebase that allow function of plugins to be called. This will allow your plugin the following features:

- Ability for your plugin to be submission-based so that users can submit objects to your plug-in. You can then visit the command and control center in Geeklog to moderate the submissions for your plugin.
- Allow your plugin to show up in the Admin block and User block on each Geeklog page.
- Allow your plugin to be searched via the Geeklog search page.
- Allow stats for your plugin to show up on the site statistics page.
- Allow your plugin the ability to use Geeklog's comment engine.
- Allow you to use the power of Geeklog's code library (lib-common.php) in your own plugin code.
- Allow you full flexibility on what your plugin does. Geeklog does not dictate your plugins power.

## Functions for writing plugins

The below functions are what you need to write your own plugin including any extra parameters that you need to pass in. Towards the end of the page, there is also a Description of the API, just incase you need it to help understand in the plugin process.

Note about <plugin name>: You will see references to <plugin name> in all the functions below. The <plugin name> values will come from you the name of your plugin tarfile. All plugin tarfiles have a strict naming convention that they must follow and it is:

> <plugin name>_<plugin version>_<geeklog version>.tar.gz
> e.g. `photos_1.0_1.3.tar.gz`

## Moderation functions

First note that there are limitations in the current Geeklog codebase that will force you to name your plugin tables used for submission in a specific manner. All moderated Geeklog items such as stories and links are comprised of two tables. The first is a main table where all visible items are stored. The second is a submission table where submitted user items sit until an administrator approves them. When approved the item is moved from the submission table to the main table. So for example, if you are writing a book review plugin that allows users to submit book reviews then we will pick bookreviews for your main table (this MUST also be your plugin name you pick) and then your submission table MUST be named bookreviewssubmission. Why force the names? Because in the geeklog code the submission table for all stories is coded as <main name>submission. So since we picked bookreviews for our main table (and plugin name) the submission table must be named bookreviewssubmission.

If you want your plugin to be moderated like Geeklog stories and links then you must implement these functions.

Table 1. Moderation functions
Function | Description of Function
--- | ---
plugin_submit_<plugin name> | Shows the submission form for your plugin.
plugin_itemlist_<plugin name> | Shows any items needing moderation for your plugin on moderation.php
plugin_savesubmission_<plugin name> | Saves submitted item from a user in <plugin name>submission table
plugin_moderationdelete_<plugin name> | Takes an ID into <plugin name>submission table and deletes it
plugin_moderationapprove_<plugin name> | Takes an ID into <plugin name>submission and moves it to the main table called <plugin name>
plugin_moderationvalues_<plugin name> | Returns the primary key column name, the main table name (called <plugin name>) and the list of fields from that table that you'd like to have show up on the moderation page.

## Admin and User Menu functions

If you want your plugin to effect the Admin and User Function blocks that show up on every Geeklog page then you must implement these functions.

Table 2. Admin and User functions
Function | Description of Function
--- | ---
plugin_adminoptions_<plugin name> | Will show options under the Admin Functions block for your plugin
plugin_getuseroption_<plugin name> | Will show options under the User Functions block for your plugin
plugin_adminedit_<plugin name> | Shows the links at the top of admin/plugins/<plugin name>.php for New and Admin Home. This is for consistency sake only
plugin_submissioncount_<plugin name> | Shows the number of submissions pending for you plugin. This is usually just "dbcount(<plugin name>submission);"
plugin_cclabel_<plugin name> | Returns array of your plugin image and a label for your plugin. This is called to show your plugin in the command and control block on moderation.php

## Search Functions

If you want your plugin to be searchable, implement these functions.

Table 3. Search functions
Function | Description of Function
--- | ---
plugin_getsearchtypes_<plugin name> | You will probably want to add a new type in the Type drop down on search.php. This function prints the option tags needed. make sure that the value tag is <plugin name>
plugin_dopluginsearch_<plugin name> | Takes the search criteria and lets you build search results for your plugin. This returns a string array of table rows, one row for each record returned by your search.

## Comment Function

If you want your plugin to support comments and use the Geeklog comment engine, then you need to implement these functions in your plugin functions.inc file:

Table 4. Comment functions
Function | Description of Function
--- | ---
plugin_commentsupport_<plugin name> | This function does not take any parameters but simply returns true if this plugin supports comments. This call is made in Geeklog code (example: article.php) to determine if it should redirect handling to the plugin.
plugin_handlecomment_<plugin name> | This function expects the comment id (primary index in the comment table) and and type of operation (either 'save' or 'delete') to perform on the comment. It will update the plugin record with the total number of comments for this plugin item. It then handles the refresh or redirection of the user back to the plugin instead of the main site page.
plugin_commentform_<plugin name> | This function expects a number of parameters and is called from Geeklog article.php and comment.php. Parameters are: comment_id (primary key), comment_mode (nested, flat, threaded, none, order (Ascending or Descending) and reply (Was the reply submit button used on the comment bar). Only comment_id is mandatory.
plugin_commentparent_<plugin name> | Optional function which can be called from your plugin_commentform function to also display the plugin parent above the comments. This is how Geeklog articles are displayed with the story and then the comment bar and associated comments.

## Stats Function

If you want your plugin to show up on the stats page then you must implement this function.

Table 5. Stats function
Function | Description of Function
--- | ---
plugin_showstats_<plugin name> | This function takes a showsitestats flag. If set to 1, this function shows the overall stats for your plugin in the site statistics box. If it is set to 2 it shows the statistic blocks for you plugin (similar to Top Ten Viewed Stories and Top Ten Commented Stories).

## Uninstall Function

If you want to give your plugin the ability to uninstall itself then you must implement this function.

Table 6. Uninstall function
Function | Description of Function
--- | ---
plugin_uninstall_<plugin name> | This function does not take any parameters. The plugin should try and uninstall itself, especially removing all its tables and data structures from the database. The function should return `true` if the uninstall succeeded and `false` if it failed.

## User Functions

For some plugins, it may be necessary to track creation and deletion of user accounts.

Table 7. User functions
Function | Description of Function
--- | ---
plugin_user_create_<plugin name> | This function is called when a new user account has been created. The only parameter passed is the user id. This function does not have a return value.
plugin_user_delete_<plugin name> | This function is called when a user account has been deleted. The only parameter passed is the user id. This function does not have a return value.

## Profile Functions

Plugins can add blocks or individual items to the user profile.

Table 9. Misc. functions
Function | Description of Function
--- | ---

plugin_profilevariablesedit_<plugin name>

This function is called when Geeklog is about to display the edit form for a user's profile. The plugin is given the user id and a reference to the template of the edit form. It can now add its own variables and input fields to the form.
This function does not return anything. The plugin should use the template functions (`set_var` etc.) to add things to the template.

plugin_profileblocksedit_<plugin name>

This function is called when Geeklog is about to display the edit form for a user's profile. The user id is passed as a parameter to this function. The plugin can return the HTML for a block (including block header and footer) that it wants to be displayed on the profile edit form. When a plugin asks for several items, it may make more sense to group the items this way. Otherwise, you may want to use `plugin_profilevariablesedit_<plugin name>` (see above) instead.
The function is expected to return the HTML for a block or an empty string.

plugin_profilevariablesdisplay_<plugin name> | This function is called when Geeklog is about to display a user's profile. The plugin is given the user id and a reference to the template of the profile. It can now add its own variables to the profile. This function does not return anything. The plugin should use the template functions (`set_var` etc.) to add things to the template.
plugin_profileblocksdisplay_<plugin name> | This function is called when Geeklog is about to display a user's profile. The plugin is given the user id and can now return the HTML for any additional blocks that it wants to be displayed on the profile page. The function is expected to return the HTML for a block or an empty string.

## Misc. Functions

The following is a list of (optional) functions for misc. purposes.

Table 9. Misc. functions
Function | Description of Function
--- | ---

plugin_centerblock_<plugin name>

Plugins can display a block in the site's center area, i.e. among the stories. This function is called several times during rendering of the site's index page. The parameters will tell the plugin where on the index page the block would appear.
Parameters are `where` (1 = top of page, 2 = after the featured story, 3 = bottom of page), `page number` and the `topic id`. `where` can also be 0 which means that the plugin can take over the entire page if it wants to (in this case, it will have to return the HTML for the entire page, i.e. including site header and footer).
The function should return the complete HTML for the block (including header and footer) or an empty string.

plugin_getheadercode_<plugin name> | Plugins may add additional lines to the site's `<head>` tag by implementing this function, e.g. Javascript functions or additional Meta tags. The function should return a concatenated string of all its extra header code.
plugin_whatsnewsupported_<plugin name> | Plugins can add their own section to Geeklog's What's New block by implementing this and the following function. The function should return an array of 2 strings. The first string is used as the headline for the plugin's section in What's New and the second string is used to indicate the timespan that the entries in this section cover (e.g. "last 2 weeks").
plugin_getwhatsnew_<plugin name> | This function should return the actual new entries to be listed in the What's New block (as an array) or a string to be displayed in case there are no new entries.

## Implementing your Admin Interface

The Geeklog Plugin API is just that an API. You obviously have to write all your plugin code yourself. We have put stubs in place to link to you Admin Interface. You admin page(s) will be in http://yourgeeklogdomain/admin/plugins/<plugin name>/

The first page of your administration interface must be named index.php and it must be in the above directory. Whether or not you use more than one page for your Admin interface is completely up to you.

Please note that the location of your admin page isn't optional. For organizational purposes it is important that you follow the standards outlined in this document.

## Preparing your Geeklog Plugin Distribution

### The plugin tarfile

All Geeklog plugin tarfiles should use the following naming convention:

> <plugin name>_<plugin version>_<geeklog version>.tar.gz

### Descriptions

<plugin name>:
  this is one of the single most important values you will choose for your plugin as it dictates the following:
  - The exact API function names that the Geeklog code will try to call for your plugin
  - The exact directory within the webtree to put all your plugin code
  - The exact directory within the admin directory to put your admin code
  - If using moderation, the exact table name main table being moderated
  - If using moderation, the submission table will be <plugin name>submission
<plugin version>:
  used during the installation process to determine if you are attempting to upgrade a plugin or do a new installation. It is also checked to verify that you aren't trying to install and old version of the plugin when a new installation already exists.
<geeklog version>:
  this is the Geeklog version the plugin works under.

The organization of your tarfile is standardized as well. For each directory and file a description is given. Your base plugin directory when you create the tarfile should be <plugin name>. Under there you will have the following:

config.php:
  configuration page for your plugin. We'd prefer you to data-drive most the values if possible but using config.php is fine. This file can be called whatever you want...you are not restricted.
functions.inc:
  this is the file where you implement the Geeklog API and where your plugin code should reside. It MUST be named this because we automatically include all enabled plugins function.inc files at the bottom of lib-common.php. Note that this means you have access to all the functions in lib-common.php in your plugin code.
lang.php or language/ directory:
  the language file(s) for your plugin. You should include this file in your functions.inc.
  We recommend that you use a language directory and have a seperate language file for each supported language (english.php, etc.), mirroring Geeklog's behaviour and selecting the language file based on the user's preferred language (falling back to english.php if you can't find a language file for the selected language).
table.sql
  the DDL needed to modify the Geeklog database so that your plugin will work.
  Note: you must provide an entry in the plugin table in your database. Without it, Geeklog will not know your plugin exists.
  Example:
  `REPLACE INTO plugins (pi_name, pi_version, pi_gl_version, pi_homepage, pi_enabled) VALUES ('photos', '0.1', '1.2.2', 'http://www.tonybibbs.com', 1);`
data.sql
  sample data for your plugin
README
  standard readme for software
/docs:
  includes any documentation you may want to provide for your plugin such as history, to-do, etc
/admin:
  includes only your admininstation pages
/public_html:
  include your regular web pages
/updates:
  includes all update sql and scripts. if you are writing an update SQL script be sure that you name it update_<previous version>.sql. The way this work is if you have version 0.1 installed for a plugin and you are installing version 0.2 the code will look for the update script for the currently isntalled version (0.1) and if it finds it, in this case update_0.1.sql then it will execute it automatically.

## How To Install A Geeklog Plugin

Note: Up until Geeklog version 1.3.4, there was an automatic install procedure for plugins. This, however, caused too many problems and support issues and has been removed from later versions. The manual install as outlined below is now the recommended way to install a plugin and should work for both old and new versions of Geeklog.

For details, you should always refer to the README that comes with the plugin. In general, however, a plugin will be installed like this:

1. Depending on your setup and server access, you should either upload the tarball and unpack it remotely or unpack the tarball locally and upload the extracted files and folders afterwards.
2. The public_html directory in the tarfile is copied to the webtree under <plugin name>. e.g. if my geeklog web is in /path/to/geeklog/public_html/ then the public_html from the tarfile is copied to /path/to/geeklog/public_html/<plugin name>
3. The admin directory in the tarfile is copied to the admin webtree. e.g. if my geeklog admin webtree is in /path/to/geeklog/public_html/admin/ then the admin directory from the tarfile is copied to /path/to/geeklog/public_html/admin/plugins/<plugin name>
4. Call the plugins install script at http://yourgeeklogsite/admin/plugins/<plugin name>/install.php
   - If this is a new install (plugin doesn't exist in plugins table) then table.sql is executed and then data.sql is executed
   - If this is an upgrade that the necessary upgrade_<version>.sql script is searched for and, if found, executed.
5. That's it!

## Deliver Your Plugin!

Because Geeklog Plugins can affect a Geeklog installation and the users filesystem, our policy is we will not endorse third party plugins unless they have been tested by the Geeklog Development team. Why? We will make sure that your plugin installs successfully and doesn't have any adverse behavior. Assuming your plugin checks out, we will put your tarfile on our site where it can be downloaded by Geeklog users. You can sumbit your plugin to our site at http://www.geeklog.net

## Description of the Geeklog Plugin API

This is the function reference for the Geeklog Plugin API, as contained in the plugins.php file. This is provided strictly for reference sake. You, as a Geeklog Plugin Developer, will not need to modify these functions nor make calls to them as that has already been handled in the Geeklog codebase. We do, however, encourage suggestions on how you think we can make this API better.

## Moderation Functions

These are the functions used to allow your plugin to access the moderation system.

Table 1. Moderation Functions
Function | Description of Function
--- | ---
SubmitPlugin | This function loops through all enabled plugins and calls the plugins plugin_submit_<plugin name> method so that a plugins submission form is shown to the user.
GetPluginModerationValues | Responsible for calling the plugin_moderationvalue_<plugin name> method so that the plugin specific values can be set so that moderation can occur.
ShowPluginModerationLists | Loops through all enabled plugins and call itemlist() so that all items needing moderation for the plugin shows up in moderation.php
ShowPluginModerationOptions | Loops through all enabled plugins and calls the plugin_cclabel_<plugin name> method so the plugin shows in the command and control center.
SavePluginSubmission | Loops through all enabled plugins and calls the plugin_savesubmission_<plugin name> method so that the plugin submission for a specified plugin gets saved.
DoPluginModerationDelete | Calls the plugin_moderationdelete_<plugin name> method of a specifid plugin so that a submission is deleted
DoPluginModerationApprove | Calls the plugin_moderationapprove_<plugin name> method of a specified plugin so that the submission is approved.

## Admin and User options functions

These are the functions used to allow your plugin to access the admin and user system

Table 2. Admin and User options functions
Function | Description of Function
--- | ---
ShowPluginAdminOptions | Loops through all enabled plugins and calls their plugin_showadminoption_<plugin name> so that the plugin shows any option(s) they need under the Admin block.
ShowPluginUserOptions | Loops through all enabled plugins and calls their plugin_showuseroptions_<plugin name> so that the plugin shows any option(s) users need in their User Functions block
HandlePluginAdminEdit | Calls the plugin_adminedit_<plugin name> method so that the "new <plugin name> | Admin Home" links show up at the top of admin/plugins/<plugin name>.php. This is implemented strictly for consistency of the UI
GetPluginSubmissionCounts | Loops through all enabled plugins and calls their plugin_submissioncount_<plugin name> method so that the number of submissions for plugins gets displayed

## Search functions

These are the functions used to allow your plugin to access the search system

Table 3. Search functions
Function | Description of Function
--- | ---
GetPluginSearchTypes | Loops through all enabled plugins and calls their plugin_getsearchtypes_<plugin name> method to get any plugin specific values that need to show up in the Type drop down on search.php
DoPluginSearches | Loops through all enabled plugins and submits the search criteria to the plugin_dopluginsearch_<pluginname> method so that the plugin can perform it's own search

## Stats functions

These are the functions used to allow your plugin to access the stats system:

Table 4. Stats functions
Function | Description of Function
--- | ---
Show Plugin Stats | Loops through all enabled plugins and calls the plugin's plugin_showstats_<plugin name> method so that statistics can be reported for the plugin