PHP plugin meta data

Plugins by this specification, are all .php scripts that carry a list of meta information fields topmost in their first comment block. Typically this looks like:

<?php
/**
 * api: php
 * title: Example Plugin
 * description: To show in plugin meta data specification.
 * type: functions
 * category: contrib
 * depends: plugin2
 * config: <const name="EXAMPLE1" value="1" description="help" />
 *     <var name="var[name]" value="..." type="text" title="Var2" />
 * author: nobody
 * license: GNU LGPL 2.1
 * 
 * And some ordinary (longer) description or help text here.
 */
some_code_follows(...);
?>

This name:value pair syntax is different from that of phpDocumentor to prevent conflicts. The comment block can even be a list of hash # or double slash // comment lines instead. Any following text is kept as help, and phpDoc @tags could round it off.

It's important to understand that this plugin meta data stands on its own. It does not itself enforce any specific plugin API or management scheme. The actual code inside such .php plugins, or their innovocation, hook registration and interaction is fully left to an application. And this specification is strictly about mere .php plugin scripts. It doesn't prescribe "modules" (zip/tgz collections) at all.

meta fields

Plugin meta data fields are human readable. But they can also bring administrability to the dozens of .php scripts that often linger around. Many fields are optional, most are case-sensitive, a few are just for presentational purposes:

api:
Specifies which application API this plugin adheres to. Usually contains an application name (yourapp). Often however just "php", to announce it as generic function collection, without special bindings.
id:
DO NOT USE THIS! Every plugins id is derived from its filename - just strip the path and .php suffix and you have it.
In rare cases, a plugin might override this value, and set its id (used in depends: fields, for example) itself. For common plugins it is probably a bad idea to do that.
title:
Displayed name of the plugin. The basename of the .php file is used as plugin id, but to get displayed in admin areas it needs a real title.
description:
Short infomercial about the plugin.
category:
Plugin files might be grouped into directories (unless they are part of a module and have their own). But for displaying there should be a more generic grouping/description scheme.
author:
Who wrote it.
license:
Better give short names, like "GNU LGPL 2.1+"
url:
Homepage URL for plugin. This field is called url: and not uri:, because while the term "URI" aquired a buzzword sound, things like 'urn:x-id:pn5mMF2:x_af' are not exactly useful in this context.
update:
Plugin direct-download link for automatic updates.
version:
Plugin version. It's best to use non-fancy version numbers like "1.2" at most. For anything more interesting, use a CVS/SVN revision: field instead.
priority:
How important is that plugin. Usually just "optional" or "contrib", because this field is reserved for default plugins - which might be "core" or "required" for an application to run at all. Special values:

core, required, default, standard, base, recommended, important, optional, extra, contrib, bonus, rare, deprecated, never, hide, auto, ...

But you could just leave that out. Apart from "required" this does not advertise plugins specifically.
type:
This field can be used just informational (like category:), but might have special meanings for some application api:s. In fact there might be a few special names here:
output
Plugin does not define/register functions, but instead just throws HTML content out, as soon as it is include()d.
functions
Just provides functions. (With "api: php") But does not register them with the appl.
class
Provides classes. Like "functions".
intercept
Uses hooks which might interrupt the flow of the application.
mangle, transform
Modifies processed data. Maybe some content filter.
api
Provides an api: itself. (For example, an PHP application framework, or class lib like PEAR or Horde). If that's the case add a "provides: api:whatever" as well, so other plugins might specify it as dependency.
virtual
File only contains depends: field.
database
Other common typisation for database driver.
auth
User management and stuff?
page
Outputs a page, but needs to be invoked.
Remember that your application is often better off with its own type: list. This is similar to category: in some way, but provides a more technical (non-user) grouping. So that special plugin types can be treated specifically with. And of course the possible values should really be general.
hooks:
If an application api: provides a plugin registry or something like that, it is typically categorized by names/ids. If that's the case, add a list of the used plugin hooks here.
depends:
Comma-separated list of plugins which need to be present, when the current gets enabled.

It is currently not supported by libconfig, but in future this field might also hold version numbers "plugin (>=2.1)". For most systems this would however be overkill and just a plaything. It's probably best to rather increase a version suffix in api: names and plugins, if their API actually changes in some incompatible way.

conflicts:
Reverse dependency. Often removes the other plugin.
suggests:
Non-strong dependency.
provides:
Virtual plugin names.
sort:
Dependencies influence plugin orders already, but some code might still need to be loaded before others. Group plugins with sort: numbers then. Default is 0. Settings start at -100. DON'T OVERDO THIS. It was actually implemented for early database initialization or core-code-as-plugins apps.
config:
XML-like field block for configuration settings. See next section...
x_other:
You can add other fields as you see fit. They firstly benefit users, but might have specific meaning in your app. Underscores are allowed, but hyphens currently not.

config: field

Plugins are very often accompanied by configuration options. To prevent the traditional repetetive code in admin tools, this specification simplifies this need to the most common use cases. While the settings are called (and probably used as) "variables" and "constants", it is again not prescribed how or where they actually get accessed or stored.

The config: field syntax uses pseudo-XML to keep it terse. And it may span multiple lines, so it can hold more than one variable or constant:

<var name="only_arrays[field]" value="1" title="Variable" />
<const name="DEFINE_CONSTANT" value="default" title="Const" />

The pseudo XML attributes are as follows:

name=
Constants should be all-uppercase. Variables must be arrays, and written in PHP form submission style - without leading $ and array index quotes.
value=
Specifies the default value. Take care that it is really called value= and not default.
type=
Variable/Const type. Can be "boolean" or "text" or "multi" (for select lists see below). A new type is "array".
title=
How to display the setting.
description=
Short help text for the setting.
sort=
(optional) Like for plugins.
category=
(optional) Settings inherit their groups from plugins, but might be categorized differently.
set=
set="always" forces that the default value gets written to the configuration data store. Else configuration settings are assumed to be default-defined in the application, and need not be present in the config file.
multi=
If the type= is "multi", then the setting provides a drop-down select box. This field contains alternatives, in then otation: "value=title|value2=title2|value3=title3" or just: "value1|value2|title3|value4"

The default entry is set by value= as usual.

Take care that there is no field named default - it's called value= here!

Besides variables and constants, there might be other configuration settings, like <sql/> or even <exec/>. This implementation does not care about them, but possible application options might be:

<var name="config[user_list][]" type="array" multi="name|pw" title="user settings" />

<const name="USE_HTML5" type="boolean" title="HTML5 usage" descriptions="moar features"/>

<sql name="cid_mergeComments" type="text" title="comments+" table="db_settings" />

The "array" type is somewhat special. All other config variables are scalars. The multi= option for select lists just predefines a list to choose from. However "array" variables are listed as such in the configuration file. Multiple lines like $config["varname"][] = array("...", "..."); are merged into a singular value (hence the [] trailing). There are no named array indexes in the configuration file, but the multi= option for configvar can name the individual fields for the admin UI. (Beware that this "array" type is specific to libconfig/libconfigedit. It's not standardizable, because a SQL storage couldn't provide array types.)

plugin management

This specification only defines the general syntax and some default fields. How plugins are organised into directories, their meta data buffered, or how they actually get invoked by the application, is left undefined.

For an examplary implementation, using a simple 'config.php' script and include() commands for managing plugins, see genericphpconfig and its "lib/pluginmetadata.php".


application modules

Geeklog, Joomla, DokuWiki, BitWeaver, e107, Drupal, MODx, Tiki, XOOPS, Typo3, Serendipity, Moodle, PhpWiki, MediaWiki all define plugin APIs of their own. Typically these are array()- or object-structures in the plugin code itself, and a function registration scheme or prescribed function names.

Most of them provide this as part of some means of installing "modules", which are often made up of code scripts and associated data files. Then it's nevertheless possible to augment contained .php scripts with PMD. And if no homebrew module organisation scheme is yet in place, one might want to use special installation plugins for that purpose. Using a plugin of "type:install" or "deinstall" and eventual "sql:<query..>" fields for example, or a "api:cms-setup", and even a "list:" of contained filenames.

Such a recommendation might be part of later revisions.

similar schemes

This specification is loosely modeled after similar schemes in multiple other PHP projects. It just "standardizes"

WordPress
The WP plugin descriptions differ only in that they use "Plugin Name:" instead of "title:", and lack an "api:" field, and they prescribe a restricted comment block format.
BitWeaver
Uses module packages, with a seperate meta description text file. Different format and fields, though.
ewiki
This plugin scheme was partially implemented in ewiki. It used separated .meta files instead of merged .php plugin descriptions however. genericphpplugins was a preparation for ewiki3.