Joomla! 1.5 is designed to be augmented and reshaped by means of extension rather than core code modification. Creating extensions can be quite complex, partially because Joomla! 1.5 implements a complex, but generally cohesive, object-oriented design and partially because documentation is sparse, inconsistent, and incomplete.
This note concentrates on the XML manifest files which are used to describe, install, and uninstall four of the five extension types: components, modules, plugins, and templates. The fifth type – languages – does not appear to require a manifest – yet.
WARNING: Use at your own risk. These are my observations after reading the code in <joomla-root>/libraries/joomla/installer/adaptors from the 1.5.3 stable release.
A relatively easy to understand the differences between the five types of extensions is to how they are used a rendered web page.
A Joomla! web page has a central content area and several areas around the central area (banner across the top, left and right columns, footer, bread-crumb area, etc). We will call the ‘content area’ the Content Area and everything else the Other Stuff. Here’s how things work:
Of the five types of extensions for Joomla! 1.5, four require manifest files. The manifest file gives complete information about an extension – including:
It is formatted as valid XML as defined by the document type definition at: “http://dev.joomla.org/xml/1.5/component-install.dtd”
Manifests are logically structured in N sections. Each section contains zero or more XML elements which should occur in order as defined in the DOCTYPE definition – which is the order they occur in this note.
Application: All
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/component-install.dtd">
<install type="component" version="1.5.0">
... contents of manifest ...
</install>
Everything here is boilerplate and copied verbatum except the install attributes. These required attributes are:
Application: All
This section identifies the author, describes the purpose of the extension, and defines the terms of use and ownership. This is pretty straightforward.
<name>Hello World</name>
<!-- The following elements are optional and free of formatting conttraints -->
<creationDate>2007 01 17</creationDate>
<author>John Doe</author>
<authorEmail>john.doe@example.org</authorEmail>
<authorUrl>http://www.example.org</authorUrl>
<copyright>Copyright Info</copyright>
<license>License Info</license>
<!-- The version string is recorded in the components table -->
<version>Component Version String</version>
<!-- The description is optional and defaults to the name -->
<description>Description of the component ...</description>
Notes:
Application Components ONLY
An install element CONTAINED within the global install element contains queries which create the database files for the component.
In this case, neither the type nor the version attributes are processed. (CHECKTHIS)
It may contain sql or queries elements. At least one sql or queries element must be present, although more than one of both may exist.
Note: queries is deprecated. The preferred joomla! 1.5 method is to use sql files.
<install>
<sql>
<file>name of SQL file</file>
<file>name of SQL file</file>
</sql>
</install>
Application: Components ONLY
The uninstall element should drop all the tables created by the install element. Like the install element, it must contain one or more sql and/or queries elements defining how to delete the files.
Note: queries is deprecated. The preferred joomla! 1.5 method is to use sql files.
<uninstall>
<sql>
<file>name of SQL file</file>
<file>name of SQL file</file>
</sql>
</uninstall>
Application: Components and Templates
Joomla! divides itself into a front end and a back end (or administrative) sections. The manifest reflects this by putting all the back end menu, file, languages, and media inside the administration element.
The administration element is required.
<administration>
<menu>...</menu>
<submenu>...</submenu>
<files>...</files>
<languages>...</languages>
<media>...</media>
</administration>
All sub-elements of the administration element are optional. If present, their contents are copied into subdirectories of joomla! installation as follows:
<administration>
<files>...</files>
<languages>...</languages>
</administration>
WARNING: I haven’t tested this, nor have I read the code. I don’t know what this is supposed to do or what it actually does.
Application: All
files are closer to the meat of the install. A files element contains filename and folder elements – which are the actual files and directories which make up the extension.
Note: for components only in contrast with the most other elements in the manifest file, you can have more than one files element. This allows groups of files to be sucked out of different source directories. This is probably a good thing if you are building on some other product and want to keep all of its source intact, but doesn’t seem too useful otherwise. [of course, I could be wrong – often am]
Module, plugin, and template installations only process one files element.
<files folder="source-directory">
<filename>path to file relative to source-director</filename>
<folder>path to folder relative to source-directory</folder>
</files>
Four Notes:
Application: All
<languages folder="source folder">
<language tag="language identifier">path to language file</language>
</languages>
languages elements may occur in the main body – in which case they belong to the front end (or site) – or within the administration element.
The folder attribute is optional. As usual, it specifies where the language files are copied FROM.
There must be at least one language element within a languages element. Notice that the tag attribute is required. It specifies the language – and hence the subdirectory of the ‘language’ folder into which the language file will be copied.
The language file path should be simply the file name because the installer will put it away in the correct directory.
Application: Component, Module, Plugin
The media specifies image files to copy. It is supposed to work in both the administration and main section [site or front end], but elements in the administration element are ignored.
<media folder="source folder" destination="destination folder">
<filename>media file path</filename>
</media>
Notes:
Application: Components
Menu elements are a little confusing and I have not installed extensions (or core elements) which use this feature of the manifest file. This is deduced from the code in installer.php. You’ve been warned.
First of all, in spite of the what the component-install.dtd file says, the code in the installer only looks for one (1) direct menu subelement of administration and one (1) submenu direct subelement.
NOTE: both are optional; a reasonable default top level menu entry is created if if the menu element is missing. submenu is only required if there are sub menus.
This is used to create the top main menu in the Components Drop Down menu.
<menu attributes>menu name</menu>
Attributes are:
A menu element may only occur in the administration element. menu element data is used to populate the #__components table.
This is used to create Submenu of the top menu in the Components Drop Down Menu
Format is:
<submenu>
<menu attributes>first sub menu name</menu>
<menu attributes>second sub menu name</menu>
. . .
</submenu>
For each of the menu elements, element content is used as the menu name and the attributes are used as:
<installfile>path to installation script file</installfile>
<uninstallfile>path to uninstall script file</uninstallfile>
These two elements allow for special scripts to be run during installation and un-installation.
The designated file must be a *php script which contains a function named com_install() and com_uninstall(), respectively.
com_install() is run without arguments after everything in the manifest has been installed, so the function has full access to all of the component’s parts.
Similarly, com_uninstall() is run, without arguments, before anything has been uninstalled from the distribution, so, again, the function has full access to all of the component’s parts. [Note – this makes it useless for removing directories from the media folder]
The *params element defines zero or more param elements – which (not surprisingly) define parameters.
<params addParameterDir="path">
<param attributes>param name OR
<option value="some value">option name</option>
</param>
</params>
params has a single attribute: adParameterDir – which is ignored by default.
Each param element can have a whole slew of attributes. The installation default action is to discard any param which does not have both a name and default attribute and to ignore the other attributes.
At present, default handling is used for components, modules, and plugins. params are ignored in template installations.
The only possible explanation I can think of is that the manifest files are re-parsed during administrative activities to acquire the parameter lists, attributes, and values necessary to set options for components, modules, plugins, etc.
None known
None known.
Templates have 3 ‘necessary’ elements: files, images, and css. We’ve already covered files above. Neither images nor css is listed in the DTD file and the code works without either one.
I don’t think the code will work correctly with either images or css elements in the ‘templateDetails.xml’ file because the contents of both should be stuffed into <joomla-root>/templates/<template-name>/images or css/ and the current code will dump them into the template-root directory – i.e. one level up. I guess you could put the appropriate prefixes in the ‘css’ or ‘images’ elements, but you you still have to put in a filename entry for every item. It’s probably legacy code or an option for the future.
NOTE: both ‘css’ and ‘images’ elements are processed by JInstaller::parseFiles() - which returns the number of files processed [0 for css and images] or false on failure. Kindly parseFiles() returns 0 if it can’t find the element it’s asked to process; template.php does an identity (===) compare against false, so everything works. This feels fragile to me.
The positions element lists the positions which modules may occupy in the template. The usual list is [taken from the Milkyway template]:
<positions>
<position>breadcrumb</position>
<position>left</position>
<position>right</position>
<position>top</position>
<position>user1</position>
<position>user2</position>
<position>user3</position>
<position>user4</position>
<position>footer</position>
<position>debug</position>
<position>syndicate</position>
</positions>