+++ /dev/null
-DEBIAN GFORGE PLUGINS HOWTO
---------------------------------
-
-Here is a short HOWTO explaining how plugins work in Debian
-GForge, and how to make a new one.
-
- It was written by Roland Mas <lolando@debian.org>.
-
-WHAT PLUGINS ARE, AND WHY THEY ARE USEFUL
------------------------------------------
-
- Plugins are extensions to the "core" of GForge, 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
-GForge 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
-GForge, 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 GForge-proper maintainers team] will maintain some sort
-of list of allocated plugin names so that different plugins get
-different allocated identifiers, see below.
-
-- 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.php and User.class.php: 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. Also
-provided are setPluginUsage() methods, taking a plugin name and a
-boolean value as arguments and returning true on success and false on
-failure.
-
-- A plugin should not change the existing files. Of course, it will
-need a way to adds links to its own web pages. This is done by a
-"hook" system. Each plugin can hook itself up to a number of hook
-points in the main code, and execute arbitrary code when that point is
-reached. Basically, the plugin registers itself to a global object
-(of the PluginManager class, if you want to know). You have to call
-the register_plugin() function, providing it an object of a subclass
-of the Plugin class that is provided by the main code. That object
-must provide a GetHooks() method, which returns a list of hook names.
-Whenever one of these hooks is encountered, the object's CallHook()
-method is called with the hook name and extra parameters that depend
-on the hook. Adding a link to your page in some place is just a
-matter of "subscribing" yourself to the hook that is in the
-appropriate place, and printing the appropriate link whenever your
-CallHook() method is called from that place.
-
- Registering your plugin is done by providing a
-/usr/share/gforge/plugins/<pluginname>/include/<pluginname>-init.php.
-It will be parsed by the PluginManager object. That file should
-contain a call to register_plugin(), passing it an object of the
-appropriate class. See the helloworld plugin for an example.
-
- The hooks are managed centrally by the GForge code maintainers.
-If you need one, please ask, we'll add it. The current list of
-hooks is provided at the end of this document.
-I rely on you plugins developers to provide more ideas :-)
-
-- Plugin-specific web pages should reside either in the /plugin/*/
-URL-space (that is, plugin "foo" will probably put its files in
-/usr/share/gforge/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 GForge (Layout.class.php, HTML.class.php, 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 GForge'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 GForge 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" GForge i18n strings).
-
-- A plugin should register itself into the database using the provided
-register-plugin script on its installation, and unregister itself
-using unregister-plugin on removal. When unregistering, be careful
-to delete all the rows in tables that contain a reference to your
-plugin_id, so that the unregistration process (which deletes your row
-in the plugins table) does not fail due to referential integrity errors.
-
-HOW DO I MAKE A PLUGIN?
------------------------
-
- Your best bet would be to start with the sample "helloworld" plugin
-and change parts of it. It shows an example of most of the things you
-should need to make your plugin: PHP 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.
-
-HOW TO NAME MY PLUGIN
----------------------
-
-If you plan on distributing your plugin to the public, please contact
-the GForge maintainer with your proposed name, and we'll add it
-to the list below. This ensures that no other plugin will use the
-same name, so as to reduce the risk of name conflicts.
-
- If you only intend to keep your plugin for yourself, you might still
-contact us with your plugin name. If you're really nice, we might
-consider adding it here too, so that other people who want to
-distribute their plugin do not reuse the same name.
-
- For reference, this is the list of currently used plugin names:
-
-- helloworld, the plugin provided as an example.
-- extldapauth, a plugin allowing on-the-fly account creation from an
- existing LDAP directory;
-
-CURRENT LIST OF PLUGIN HOOKS
-----------------------------
-
-The following is a list of hooks available in GForge for plugins to utilise.
-Each hook is listed with its name, locations in the source code where the
-hook is called, and parameters that are passed into the hook and a brief
-description. There may be other hooks available, added after this section
-had been written.
-
- Hook Name : session_set_entry
- Locations : common/include/session.php
- Description: Called before checking if the user is logged in by
- reading session cookie.
- You can use this hook to handle session setup specific
- to your plugin.
-
- Hook Name : session_set_return
- Locations : common/include/session.php
- Description: Called after checking if the user is logged in by reading
- session cookie.
- You can use this hook to handle session setup specific
- to your plugin.
-
- Hook Name : artifact_extra_detail
- Parameters : artifact_id - The ID of a tracker item
- Locations : www/tracker/detail.php
- www/tracker/mod-limited.php
- www/tracker/mod.php
- Description: Use this hook to provide additional information about a
- tracker item based upon its ID.
-
- Hook Name : before_logout_redirect
- Locations : www/account/logout.php
- Description: Called once the GForge user has had their session logged
- out, and before the user is redirected to the homepage of
- the site.
-
- Hook Name : cssfile
- Locations : www/include/Layout.class.php
- Description: Used to include a CSS link element to include in the page
- layout. The hook should return a complete <link> element.
-
- Hook Name : cssstyle
- Locations : www/include/Layout.class.php
- Description: Used to include inline CSS into the page layout. The
- hook should return pure CSS, without surrounding
- <style> elements.
-
- Hook Name : group_approved
- Parameters : group_id - The numeric ID of the group
- Locations : www/admin/approve-pending.php
- Description: When a group is approved by a site admin, this hook is called.
-
- Hook Name : groupisactivecheckboxpost
- Parameters : group_id - The numeric ID of the group
- Locations : www/project/admin/editgroupinfo.php
- Description: Called when a plugin is activated for a specific group from
- the group's Edit Public Info page. Use this to perform
- actions to initialise the plugin for a specific group.
-
- Hook Name : groupisactivecheckbox
- Parameters : group_id - The numeric ID of the group
- Locations : www/project/admin/editgroupinfo.php
- Description: Used to display a portion of a form on a group's Edit
- Public Info page. It should return a HTML <tr> line containing
- two cells.
-
- Hook Name : groupmenu
- Parameters : DIRS - A reference to the array of tab URLs
- TITLES - A reference to the array of tab titles
- toptab - A reference to a string containing the name of
- the GForge tab menu in use (eg. admin, tracker)
- selected - A reference to an array index of the tabs.
- group - The numeric ID of the current group
- Locations : www/include/Layout.class.php
- Description: Used to provide a plugin specific tab in when viewing
- group pages.
- [TODO: The use of the 'group' name as a parameter is inconsistent
- with most other group plugin hooks - which use group_id.]
-
- Hook Name : groupmenu_scm
- Parameters : DIRS - A reference to the array of tab URLs
- TITLES - A reference to the array of tab titles
- toptab - A reference to a string containing the name of
- the GForge tab menu in use (eg. admin, tracker)
- selected - A reference to an array index of the tabs.
- group_id - The numeric ID of the current group
- Locations : www/include/Layout.class.php
- Description: Provides a tab for the SCM system in the group pages.
-
- Hook Name : headermenu
- Parameters : toptab - A reference to a string containing the name of
- the GForge tab menu in use (eg. admin, tracker)
- template - An HTML template giving how to add the menu.
- Locations : www/include/Layout.class.php
- Description: Used to provide a plugin specific menu entry in the header
- top menu (after: Login, Logout, My Account).
- See plugin online_help for example of use.
-
- Hook Name : javascript
- Locations : www/include/Layout.class.php
- www/include/LayoutSF.class.php
- Description: Provides a place to add inline Javascript into the page.
- The output of the hook should be pure Javascript, as it will
- be placed within an existing <script> block.
- [TODO: The output of the hook appears after the closing SGML comment marker
- and before the closing </script> element. Is this what is really indended?]
-
- Hook Name : project_admin_plugins
- Parameters : group_id - The numeric ID of the group
- Locations : www/project/admin/index.php
- Description: Provides a place for plugin authors to add a link on the
- group summary page to the admin page for a plugin.
-
- Hook Name : project_after_description
- Parameters : group_id - The numeric ID of the group
- Locations : www/include/project_home.php
- Description: Provides some space for plugin specific text on a group's
- summary page.
-
- Hook Name : project_public_area
- Parameters : group_id - The numeric ID of the group
- Locations : www/include/project_home.php
- Description: Used to provide plugin specific infos on a group's
- public area.
-
- Hook Name : scm_admin_update
- Parameters : group_id - The numeric ID of the group
- Parameters : scmradio
- A number of scm specific values generated from the
- form fields created by the scm_admin_page hook.
- Locations : www/scm/admin/index.php
- Description: When the SCM admin page is submitted, this hook is called.
- [TODO: Is scmradio actually used anywhere or is it legacy? A grep through
- the source code seems to indicate its never used!]
-
- Hook Name : scm_admin_page
- Parameters : group_id - The numeric ID of the group
- Locations : www/scm/admin/index.php
- Description: Used to generate an administrative form for the SCM
- plugin. All the form fields generated by this hook should
- be named [pluginname]_[fieldname] where [pluginname] is the
- SCM plugin name and [fieldname] is a field name for the
- form element. Using this naming scheme ensures the fields
- are properly passed as parameters to the scm_admin_update hook.
-
- Hook Name : scm_page
- Parameters : group_id - The numeric ID of the group
- Locations : www/scm/index.php
- Description: Show a page for the SCM in use by a group.
-
- Hook Name : scm_plugin
- Parameters : scm_plugins - A reference to an array of plugins providing
- SCM features. Each element is a plugin string name.
- Locations : common/scm/SCMFactory.class.php
- Description: This is used by GForge to identify SCM plugins. Any plugin that
- provides SCM features should add itself to the scm_plugins array
- when this hook is called.
-
- Hook Name : scm_stats
- Parameters : group_id - The numeric ID of the group
- Locations : www/include/project_home.php
- Description: Shows SCM specific statistics on the group's summary page.
-
- Hook Name : search_engines
- Locations : www/search/include/SearchManager.class.php
-
- Hook Name : session_before_login
- Parameters : loginname - The login as passed in from the user
- passwd - The password as passed in from the user
- Locations : common/include/session.php
- Description: Authentication plugins can use this hook to authenticate
- a user before GForge passes the authentication details on
- to its own database. The hook should return true if the
- authentication succeeds.
-
- Hook Name : site_admin_option_hook
- Locations : www/admin/index.php
- Description: Use this to provide a link to the site wide administrative
- pages for your plugin. The hook should return HTML within
- a <li> block and will appear on the Site Admin page in the
- Site Utilities list.
-
- Hook Name : task_extra_detail
- Parameters : task_id - The numeric ID for a task
- Locations : www/pm/detail_task.php
- www/pm/mod_task.php
- Description: Provides a place to include extra information about a
- task. The hook should return a <tr> row containing 2 cells
- (or colspan'ed to 2).
-
- Hook Name : usermenu
- Locations : www/include/html.php
- Description: Prints out a tab to show when displaying user pages.
- Unlike the groupmenu hook, this hook should use the PrintSubMenu
- method to display the tab itself.
-
- Hook Name : role_get
- Locations : common/include/Role.class.php
- Description: Provides a place to read role from another subsystem (LDAP, DB,
- etc...)
-
- Hook Name : role_update
- Locations : common/include/Role.class.php
- Description: Triggered when new a role is updated
-
- Hook Name : role_setuser
- Locations : common/include/Role.class.php
- Description: Provides a way to extend the way user information are stored
-
- hook Name : outermenu
- Parameters : DIRS - A reference to the array of tab URLs
- TITLES - A reference to the array of tab titles
- Location : www/include/Layout.class.php
- Description: Used to provide a plugin specific tab in main menu.
-
- Hook Name : project_public_area
- Parameters : group_id - The numeric ID of the group
- Locations : www/include/project_home.php
- Description: Used to provide plugin specific infos on a group's
- public area.
-
- -- Roland Mas <lolando@debian.org>