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.