OWS Plugin Development Guide
=============================
TODO: Write this :p
TODO: Example plugins
TODO: HTML/PDF format? Better organization of this.
TODO: What about putting this in a Wiki?
1. Introduction
2. Plugin Types
a. Filter
b. Analysis
c. Installable
d. Limit
e. Reject
3. Useful classes & functions
a. SQLSelect
b. ResultTable
c. show_result_table
4. Naming convention
1. Introduction
The purpose of plugins is to be able to provide easy third party interaction
with the OWS database. In OWS, a lot of primary functionality is implemented
as different types of plugins. The goal is for the user to have an enormous
amount of flexibility in specifying the data they want to see (while providing
sensible defaults as well), and for that flexibility to be implemented in such
a way that plugins can be very simple and take advantage of existing
functionality.
Due to human error, this document may be dated depending on the changes in the
source code, because OWS is a constantly evolving product. For the most recent
information, you are encouraged to review the source code for existing plugins
and read the comments in plugin_interfaces.php (which may have newer comments
than the plugins).
All plugins are implemented in class objects that are created once and not
destroyed until the script ends. Files implementing plugins should be placed
into the ./plugins directory. A file can contain multiple plugins. For plugins
to actually work, they must register themselves using the register_plugin
function. For example:
$bot_analysis = new BotAnalysis();
register_plugin('analysis',$bot_analysis);
Note that the register_plugin function will already be defined by the plugin
loading files, so you will not need to include it yourself.
2. Plugin Types
OWS plugins are simply PHP classes which implement the interfaces that are defined in
plugin_interfaces.inc.php. There are a number of different types of interfaces, all
of which serve different purposes. All plugins MUST implement iPlugin.
a. Filter: iFilterPlugin
These plugins are shown to users, and then run at the users request.
b. Analysis : iAnalysisPlugin
These plugins are ALWAYS run when a database upload is performed. They are
also used to define dimensions and their usage. Refer to dimensions.txt for
more information on dimension structure.
Analysis is run in a number of rounds (process stages), at the end of which
the current data is committed to the database.
If any of them return false, then the current transaction is scrapped.
c. Installable : iInstallablePlugin
This is for plugins that require extra information such as tables, field
alterations, and such to be created for their proper operation. Note that
while this is useful for analysis plugins, they do NOT have to implement this
in order to add new dimensions or modify existing ones.
d. Limit : iLimitPlugin
These plugins implement common limits for all any filter plugins that
use the SQLSelect class to do SQL queries. It allows the limit plugins to do
anything it wants to with the SQL queries.
e. Reject : iRejectPlugin
This aids analysis, in that it is used to make the size of the database smaller
depending on characteristics of the log line. This is useful if you want to write plugins to
exclude things such as spam, bots, whatever. Its also useful if you get tons of hits each day
and only want OWS to keep the history for the last 15 days, or something to that effect.
Rejection plugins should probably just DELETE records from the main fact table. After an analysis,
if the user sets $cfg['cleanup_stale'], then the analysis engine will try to automatically resolve
all dimension records to see if there is matching data in the main fact table, and delete the
dimensional data if it isn't referenced by anything else. It is set to false by default.
3. Useful Classes & functions
It should be noted that the following documentation is directly taken from
the comments above these classes and functions, so they may be slightly out of
date. If in doubt, look at the source code for the documentation. Hopefully
in the near future we can make it all automatic or something.
a. SQLSelect()
The point of this is to be able to create SQL queries and being able to modify them
easily using a standard set of filter functions without having to parse the contents
of said SQL queries. Instead, we just have to add things to this object, then call generate()
and it will return the SQL string.
Of course, you don't really have to use this. Its just so we can have standard things like
bot filtering, filtering by date, etc for every plugin without having to repeat code for it, including
the SQL interpretation thereof.
The other useful purpose of this class with the current star schema is to make it so that you
dont have to manually specify all the needed joins, it can specify them for you. :)
And of course, this will be plugin based. In the future, we can probably implement an optimizer
b. ResultTable()
Shows an associative array in a table format. This is probably way too complicated,
but it works for the moment. Variables:
@param array $headers Note: You can specify this option when you use SQLSelect to do a SELECT().
Note: The inner array of this parameter can be created with col_description();
This is an array of arrays that denotes each column to be shown at the top
of the table. If it is associative, then the columns will be matched
by key. Otherwise, it will be done in numerical order. If an entry is
not found in this array for the row, then a default value will be used.
The array will be formatted like this:
array('column_name' => array('Column Name Shown to User', $process_array), ...)
or
array(array('Column Name Shown to User', $process_array), ...)
column_name should be the actual SQL column, including things like SUM or distinct.
Basically, whatever db_fetch_assoc returns. See global $db_key_map for a better
example.
$process_array is an optional array. It contains a number of option keys, and
if an option key is not set, then the processing is not done. The possible
option keys currently are:
ww -> length to wordwrap at, not set means dont wrap
href -> this is prefixed to the contents of the column,
and then it is turned into a link
bold -> column is made bold
filesize -> if set, this interprets the column as a filesize
c. show_result_table
Wrapper around the ResultTable class to echo out the entire tableset of an SQL
operation. Of course, this wrapper provides functionality to 'page' through result sets
as well.
$query SQLSelect object. If false, then result must not be false. If you provide a
object here, then this routine will attempt to provide 'paging' through the
result sets.
$result Result returned from db_query.
4. Naming Conventions
Plugins are loaded in alphabetical order, by filename. This is to ensure
some consistancy in the plugin loading process, particularly in regard
to the placement of plugins on the OWS menu. In fact, thats probably the
only part that matters.
So, plugins should be called something like
[number] _ [name] .php
Plugins distributed with OWS by default will be of the format
[number] _ows_ [name] .php
We ask that you not name your plugins with an ows prefix so that users can
more easily distinguish the plugins distributed with OWS.
TODO: More descriptions of each type of plugin. For now, see ./include/plugin_interfaces.inc.php and the
plugins in the plugin directory.
Plugins are loaded and displayed alphabetically by filename.