Filewatcher File Search File Search
Content Search
» » » » » gforge-common_4.5.14-22etch13_all.deb » Content »
pkg://gforge-common_4.5.14-22etch13_all.deb:1012268/usr/share/doc/gforge-common/  info  control  downloads

gforge-common - collaborative development tool - shared files…  more info»



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 <>.


  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

  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.


  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 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 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.  Also
provided are setPluginUsage() methods, taking a plugin name and a
boolean value as arguments and returning true on success and false on

- 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
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

  If possible, and as much as possible, a plugin should use the layout
functions defined by GForge (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 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.


  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.


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;


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  : after_session_set
  Locations  : www/include/pre.php
  Description: Called once the GForge session has been initialised.
               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
  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
  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
  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
  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
  Description: Provides a tab for the SCM system in the group pages.

  Hook Name  : javascript
  Locations  : www/include/Layout.class
  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
  Locations  : www/include/project_home.php
  Description: Provides some space for plugin specific text on a group's 
               summary page.
  [TODO: This isn't passed in the group_id... is it of any use??]

  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
  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

  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
  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.

  -- Roland Mas <>
Results 1 - 1 of 1
Help - FTP Sites List - Software Dir.
Search over 15 billion files
© 1997-2017