The FOSSology user interface (UI) is a modular design written in PHP. Each module (called “plugins”) defines a single function. Plugins have the option to depend on other plugins, in order to extend or reuse functionality.
Plugins may depend on other plugins. If a required plugin is unavailable then the dependent plugin will be unavailable.
Beyond the plugins are a set of “common” functions. While common functions may use plugins, the common functions are always available, even if related plugins are unavailable. For example, the database connection is managed by a pluggin (plugins/core-db.php). However, many of the common functions access the database. If a plugin calls a common function when the DB is unavailable, then it will get back no results (but it will not create an error).
Plugins use a common template class (template/template-plugin.php) that defines basic functions and common variables. Plugins have the ability to set or override any of these default variables.
The external variables used by various plugins is as follows:
$State. This defines the initialization state for the plugin. See Plugin States.
$Name. This must be a name for referencing this plugin. In particular, if another plugin depends on this plugin, then this is the name that will be used to reference it.
$Version. Multiple versions of the same $Name may exist (good for debugging or upgrading). Other plugins may have a dependency on a specific $Version of $Name, but usually just want the latest greatest. The value of $Version should be a number (for sorting). The default value is “1.0”.
$Title. This string is used for HTML title tags and window menu bars.
$PluginLevel. Plugins are actually sorted in the plugin data structure. If there is some reason this plugin must come first, then increase this number (default is 10). First plugins are sorted by dependencies. If all dependencies are met, then plugins are sorted by this number.
$DBaccess. Plugins can be restricted based on logged-in user level. If the user does not have the correct access level, then the plugin is disabled. Current user levels are tied to the type of database access. The levels are:
PLUGIN_DB_NONE (0). This plugin does not use the database. Anyone can access this plugin.
PLUGIN_DB_READ (1). This plugin does read-only access to the database. Any user with read-only access can use this plugin. (This is the default access level for users who are not logged in.)
PLUGIN_DB_DOWNLOAD (2). Along with read-only access, the user may download files. This is given its own access level because “downloading” is considered “distributing software”. Since some licenses restrict distribution, this access level is restricted.
PLUGIN_DB_WRITE (3). Besides read and possible download, this plugin writes to the database.
PLUGIN_DB_UPLOAD (4). Besides read, download, and write, this plugin is used for managing uploaded files.
PLUGIN_DB_ANALYZE (5). All of the above is permitted, as well as managing analysis jobs.
PLUGIN_DB_DELETE (6). (All of the above, plus:) While adding to the database takes one set of access levels, deleting is a higher access level. The main reason this is a different access level: adding and analyzing can take time. Deleting can undo all of that effort. To prevent accidental (or malicious) deletions, this functionality is placed in its own access level.
PLUGIN_DB_DEBUG (7). This plugin is used for debugging the system. Most users won’t have a need for this. Debug plugins are permitted to do all of the above functionality.
PLUGIN_DB_USERADMIN (10). This is the current super-user. This plugin level permits doing *anything*, including creating, managing, and deleting user accounts. The basic idea: if you can create a user with specific permissions, then you might as well already have those permissions.
$LoginFlag. Some plugins require a logged in user, even if the access is read-only or “none”. The default value is “1” meaning “login required”. Set to 0 if any user (including not logged in) can access this plugin.
$NoMenu. When shown throw the web browser, all plugins default to showing the drop-down menu at the top. If you don’t want the drop down menu HTML, then set this to “0”. As an example, the folder plugin (ui-folders.php) sets $NoMenu=1 because the output from this plugin is its own menu.
$NoHTML. Similar to $NoMenu, this variable disables all default HTML, including the default CSS definitions. The AJAX plugins set $NoHTML=1 since the default HTML would corrupt the XML (or other) formatted results. If you set $NoHTML=1, then you don’t need to set $NoMenu=1 (the menu will not be there).
$NoHeader. Similar to $NoMenu and $NoHTML, this variable disables all of the default HTTP header information AND all default HTML. (Default is 0, set to 1 to disable the headers. Setting it to 1 also sets $NoMenu=1 and $NoHTML=1.) For example, the “download file” plugin (ui-download.php) does not use any default html or headers since those would corrupt the download stream.
$InitOrder. On rare occasions, a plugin may be needed to initialize before all other plugins. (E.g., the database should be initialize before all else.) Higher values will initialize first. Under normal circumstances, plugins should not need to change the default value.
$Dependency. This is an array of plugin names (set by each plugin’s $Name) that are required by this plugin. For example, if your plugin contains $Dependency=array(”db”,”ui-browse”); then it will only be available if both the plugin named “db” and “ui-browse” are available. NOTE: Dependency loops between plugins will always fail since the dependent plugins is unavailable.
Many plugins register themselves with the top user menu. These three variables similify this registration process.
$MenuList. This is the full name of the menu option, with “::” defining the path. For example, “Organize::Folders::Create” will register this plugin under the “Organize” menu heading, submenu “Folder”, using the name “Create”.
$MenuOrder. The default menu ordering is alphabetical. If you don’t want to be alphabetical, then change the menu order. The default value is “0”. Higher numbers come first in the menu. All menu items with the same $MenuOrder value are sorted alphabetically.
$MenuTarget. The top-level user menu has the ability to return content in different windows. Set $MenuTarget to specify an alternate “<a href=... target=value>” target value.
Each plugin uses a template that defines functionality at specific stages. The stages are as follows:
function Install(). This is only called when the UI is first initialized (during installation). This function should make sure all requirements are available and create anything it needs to run. It returns 0 on success, non-zero on failure. A failed install is not inserted in the system. Since this function may be called multiple times, it must check that changes are needed BEFORE doing any changes. Also, it must check for partial installs in case the user is recovering from an installation failure. The only dependency that can be assumed to work is “global $DB”, and even then, be sure to check if $DB is NULL before using it.
function Remove(). This function is only called when a plugin is being removed from the system. (Currently, nothing calls this. It is a placeholder for future functionality, like “user installable plugins”.)
Initialize(). This function is called each time the plugin is loaded. It is used to initialize any local requirements. NOTE: This function is called BEFORE dependencies are configured. This function MUST NOT dependend on any other plugins, including the database! Following the Initialize() call, dependencies are checked.
function PostInitialize(). This function is called AFTER Initialize() and after dependencies are met. This is where you should put any plugin-specific initialization that depends on other plugins. The default PostInitialize registers any default menus (the $MenuList, $MenuOrder, and $MenuTarget variables).
function RegisterMenus(). If there are other menus that you wish to register, this is the best place to do it. RegisterMenus() is called after PostInitialize().
All actual output is done in three stages. First the output stream is configured, then the output is created, and finally the output stream is closed. Calls to a plugin’s Output() can only be done while the output stream is configured.
function OutputOpen($Type,$ToStdout). If the plugin is expected to generate output, then this function is called. It defines the type of output (” HTML“, “ XML“, or “Text” – nearly always “ HTML“) and whether the output should go to stdout ($ToStdout=1) or be returned in a variable ($ToStdout=0). This function may set items like HTTP headers.
function OutputSet($Type,$ToStdout). Similar to OutputOpen, this sets the output type but must not modify the HTTP headers. OutputSet() is usually called when some other plugin is actually going to generate this output, but wants to use this plugin to generate part of the return data.
function OutputClose(). The counterpart to OutputOpen(). This function closes any output streams. There can be no more calls to Output() until OutputOpen() or OutputSet() are called again.
function OutputUnSet(). The counterpart to OutputSet().
When each plugin is loaded, its object is actually stored in an array of plugins. You can see the data structure in the Web UI (under the Hemp menu, Debug submenu, “Debug Plugins”, or simply: “Help::Debug::Debug Plugins”).
This debug view lists the array two ways. The first is the sorted array (sorted by dependencies and plugin order), listing the $Name and $State values. Anything with a state of 0 is disabled; 2 means it is fully initialized. The second view (further down the page) lists the actual object’s contents.
Plugins can find other plugins by using the common function “plugin_find_id($Name)”. This returns the array index for the initialized plugin, or -1 if the plugin is not found or not initialized. (There are other functions in common/common-plugins.php for finding a plugin regardless of state or based on the version number.) Since plugins may need other plugins, it is common to see in the code:
global $Plugins; // access the global array
/* Gain access to the plugin object */
/* The "&" ensures the use of the real plugin, and not a copy. */
$PluginObject = &$Plugins[plugin_find_id("pluginname")];
After finding the external plugin object, you can access it using “→“, for example:
$PluginObject->OutputSet("HTML",1);
$PluginObject->Output();
$PluginObject->OutputUnSet();
If a required plugin is listed in this plugin’s $Dependency array, then you don’t need to check if it exists. (If it didn’t exist, then your plugin would not be initialized either.) However, if your plugin gives optional information based on another plugin’s availability (if the plugin exists...) then you’ll want to use plugin_find_id() to test if the optional dependency is available.
/* Check if the plugin exists -- for optional dependencies; not needed for anything in
this plugin's "$Dependency" array. */
if (plugin_find_id("pluginname") >= 0) /* found it! */
else /* the plugin does not exist or is not initialized */
In general, new plugins should not need to directly scan or parse or manipulate the global $Plugins array.
While plugins may have hard-coded knowledge about other plugins, we needed a way to dynamically register plugins with other plugins. This is done through a data structure called “Menu”. This is a menu of registered plugins.
The menu structure is a linked list of registered items. Each menu object has a well-defined structure, for example:
menu Object
(
[Name] => Meta
[URI] => view_meta
[HTML] =>
[Order] => 1
[Target] =>
[MaxDepth] => 0
[SubMenu] =>
[FullName] => View-Meta::Meta
[Title] => View meta information
)
$Name. The $Name is the name of the menu object. When displaying a menu item, this is the text name that is displayed. NOTE:This is not the name of the of the plugin associated with the object. By using names, it is possible for one menu item to overwrite another menu item. (This can be very desirable.)
$Order. This alters the sort-order of menu items. All items at the same $Order are sorted alphabetically by $Name.
$FullName. This is the full path of the menu object. (It includes $Name.) The path is denoted by a series of “::”. So “A::B::C” is A with the submenu B with the submenu C. There is no limit to the path’s depth.
$URI. Each URI is in the form “/index.php?mod= URI“. (Technically, the URI in HTTP is everything after the server, but since all plugins require a “?mod=”, the $ URI is everything after this.) The $ URI is used to create hyperlinks from displayed menu items. If this is blank, then no hyperlink is created.
$Title. When using $ URI, href links can have a “title=” tag for text that pops up when the cursor hovers over the link. If specified, the $Title string is the text for the popup.
$Target. Normally hyperlinks from $ URI replace the same HTML page. However, you can specify other target windows. (This goes into <a href=... target= $Target>.)
$HTML. Menu items that are displayed do not need to contain text and hyperlinks. If you want, you can specify actual HTML to insert. (In this case, $Name, $ URI, $Title, and $Target are ignored.) The HTML may define forms, images, tables, or whatever you want...
$SubMenu. This is the link to an array of submenus.
$MaxDepth. Due to the number of submenus, it may be desirable to know how “deep” the menu tree is. This variable is set to the maximum depth of the submenu tree. For example, the top user menu in the web UI needs to know how many CSS levels to define. $MaxDepth provides that information.
While the menu structure is commonly used to define menus (the top user menu in the web UI begins with “Main::”), other menus may server other purposes. For example, all of the “micro-menus” (context-sensitive menus that appear in the upper right corner on some pages) are each defined under their own menu heading. “Browse::” is the micro-menu used by the browse plugins, “JobDetails::” is used by some of the “Show Jobs” plugins, and the “Agents::” menu allows plugins to register analysis agents.
Plugins are not expected to manage all of the $Menu structure. Instead, common functions are placed in common/common-menus.php. The main ones are:
function menu_insert($Path,$Order=0,$URI=NULL,$Title=NULL,$Target=NULL,$HTML=NULL). This inserts a menu item into the menu structure. The “$Path” is the full menu name.
function menu_find($Name,&$MaxDepth,$Menu=NULL). This returns a menu structure. (The structure is recursive, so each submenu is just another menu structure.) In this case, $Name is the path you want to return. For example, menu_find(”Main::Organize”,$Depth) will return all submenus under Main::Organize, and sets $Depth to the depth of the returned structure.
function menu_to_1html($Menu,$ShowRefresh=1,$ShowTraceback=0,$ShowAll=1). This is function is commonly called the “micro-menu” and is used to retrieve and display a micro-menu. Use menu_find() to get $Menu. The suffix “1html” means “only process 1 level; don’t recurse, and return results in HTML.”
function menu_to_1list($Menu,&$Parm,$Pre=”“,$Post=”“,$ShowAll=1). Similar to menu_to_1html(), this function returns a list of items. You can see these when browsing a directory (the “[View] [Meta] [Download]” options are actually a menu created by this function). The $Pre and $Post parameters indicate the text before and after the menu’s $Name.
Copyright (C) 2007-2008 Hewlett-Packard Development Company, L.P.
FOSSology Project documentation is licensed under the GNU Free Documentation License Version 1.2
|