DEBIAN SOURCEFORGE PLUGINS HOWTO -------------------------------- Here is a short HOWTO explaining how plugins work in Debian Sourceforge, and how to make a new one. ,-----------------------------------------------------------------------. | This is a DRAFT document! The plugin system is not implemented yet, | | and not completely designed either. Please read carefully, think | | about it, and submit comments and fixes. | `-----------------------------------------------------------------------' It was written by Roland Mas . WHAT PLUGINS ARE, AND WHY THEY ARE USEFUL ----------------------------------------- Plugins are extensions to the "core" of Sourceforge, providing extra functionality without being tightly integrated within Sourceforge proper. They are useful because they allow for independent development of third-party functionality, and they add flexibility to Sourceforge as to what features are available on a particular installation. As an example, it's been suggested to integrate a shared calendar application in Sourceforge. It's a good idea and an interesting feature, but not one that everybody wants. Thus, including it in the Sourceforge code would piss off someone. Additionnally, there might be several competing implementations for such a calnedar application. Choosing one among them would also piss off people. So it is made possible to have a system so that different implementations can exist and be installed separately. HOW PLUGINS WORK ---------------- It is expected that a plugin is just some new feature added to Sourceforge, and not a change in the behaviour of existing features. A plug-in should therefore only add files, not change existing ones. Whether these files be web pages, offline scripts, static documentation or else is not relevant. Of course, *some* changes will have to be made to the "core" files, if only to add links to new web pages, for instance. These changes are acceptable, and will be discussed below. Here come the details about how the plugin system is implemented. - A plugin will be identified primarily by a string handle, which will be static across all installations of this plugin. It should be composed of lowercase letters only, because it's going to be used in table names and we don't want namespace conflicts. For instance, if the ACME company writes a time tracking tool plugin, the handle for that plugin could be "acmetimetracker". When installed, the plugin will be assigned an integer identifier. This id might vary from site to site, and should not be depended upon. We [the Sourceforge-proper maintainers team] will maintain some sort of list of allocated plugin names so that different plugins get different allocated identifiers. - Tables in the database schema: special tables have been added to the database schema to keep track of installed plugins. They are described below (simplified descriptions): ,---- | CREATE TABLE plugins (plugin_id integer, | plugin_name character(32), | plugin_desc text, | CONSTRAINT plugins_pkey PRIMARY KEY (plugin_id) | ) | CREATE TABLE group_plugin (group_plugin_id integer, | group_id integer, | plugin_id integer, | CONSTRAINT PRIMARY KEY (plugin_id), | CONSTRAINT FOREIGN KEY (group_id) REFERENCES groups(group_id) | ) | CREATE TABLE user_plugin (user_plugin_id integer, | user_id integer, | plugin_id integer, | CONSTRAINT PRIMARY KEY (plugin_id), | CONSTRAINT FOREIGN KEY (user_id) REFERENCES users(user_id) | ) `---- "plugins" lists the installed plugins, with the numeric id, the string handle (say, "acmetimetracker") and a description. "group_plugin" is a way to store the fact that a group "uses" a plugin without needing to add a "uses_acmetimetracker" to the groups table for each known plugin. "user_plugin" is the same, for users. - A plugin may create its own tables in the same database. These tables must be named plugin_foo_* if the plugin's string identifier is "foo". One suggested table is plugin_foo_meta_data, which should be used to store the plugin meta-data, such as the installed version. The plugin can then use some code like db-upgrade.pl if its database schema changes over time. [TODO: Standardise the command/script/something below] These tables may have foreign key referential integrity constraints going from them to standard tables, but not the other way round. If they have, then a command/script/something must be provided so that the main db-upgrade.pl can disable the constraints and re-enable them afterwards in case some database schema changes are needed. Similarly, a plugin may create sequences, indexes, views, etc, provided that their names are prefixed with plugin_foo_ too. A plugin should not modify the data in tables that do not belong to it. If it really needs to, then please discuss it with us first, there might be cases where it's needed/useful. Reading those data is okay, but it must be careful not to leak any info to places/users which normally wouldn't have had access to it. - Functions in Group.class and User.class: the Group and User classes now have a usesPlugin() method. It takes a single parameter, the "acmetimetracker" identifier for the module, and returns a boolean if the particular user/group has turned on the use of that module. - A plugin should not change the existing files, except insofar as it adds links to its own web pages. Of course, these additions will have to be merged into the pages of the main package, but it should be just a matter of inserting lines like ,---- | if $this_group->usesPlugin("foo") { | echo [Link to /plugins/foo/index.php?parameters] | } `---- in the existing pages. Most plugins will probably only add these links on the project summary page and/or on the user personal pages. [TODO: Specify these hooks and how they work, implement] Additionnally, a series of hooks will be provided so that plugins do not need to change existing files for simple insertion. For instance, if the "acmecvsinterface" does not have particular needs besides a link pointing to it from the project page, it could just register its base URL to the "project-menu-features-list-hook", and the project menu would display a list of links subscribed to that hook with one parameter, "?group_id=". - Plugin-specific web pages should reside either in the /plugin/*/ URL-space (that is, plugin "foo" will probably put its files in /usr/lib/sourceforge/www/plugins/foo/) or (if the web interface is not written in PHP) in /plugin/*/cgi-bin/ URL-space (files in /usr/lib/sourceforge/cgi-bin/plugins/foo/). If possible, and as much as possible, a plugin should use the layout functions defined by Sourceforge (Layout.class, HTML.class, or whatever they're called), to ensure a consistent look and themability. Of course, the previous point only applies to plugins written in PHP. Plugins written in other languages are not excluded by this proposal, and there is no need to restrict them. Should they appear, they might need to recode some of Sourceforge's functions in Perl or another language. I see no need to restrict that either. Only thing: it would be better if the porting were as straightforward as possible. Do not reimplement, please. Just translate from PHP to Perl or whatever. If you do, please submit your translation to us, so that it can be provided by Sourceforge proper and maintained in common. [TODO: Think about that, design, implement] Speaking of languages... There should be some way to have plugin-specific language files, so that the plugins can use the standard methods used elsewhere in Sourceforge. I haven't thought about that very deeply yet, but I think it will evolve into a recommendation that the "handles" in the language files are plugin_foo_page / item (as compared to the current page / item model used for "core" Sourceforge i18n strings). [TODO: Implement those scripts] - A plugin should register itself into the database using the provided sf-register-plugin script on its installation, and deregister itself using sf-deregister-plugin on removal. HOW DO I MAKE A PLUGIN? ----------------------- [TODO: Actually implement it...] Your best bet would be to start with the sample "helloworld" plugin and change parts of it. It shows an example of everything you should need to make your plugin: PHP pages, Perl CGI pages, configuration files, bits of Apache configuration, cron jobs, etc. If you need something else, please ask, we'll discuss it, (hopefully) reach an agreement on how to Do It Right, and implement a sample in helloworld. -- Roland Mas