-
Notifications
You must be signed in to change notification settings - Fork 0
The InstallScript class
The FOF30\Utils\InstallScript
class helps you create component installation scripts which perform several common functions required for the installation and upgrade of Joomla! components.
Please note that unlike FOF 2, this installation script will NOT install FOF. For a real world example of packing up FOF with your extension please check out the Akeeba Subscriptions package manifest and its corresponding package installation script.
The contents of your package need to follow a specific folder layout. Here's the proposed layout:
+-- backend Component files under site's "administrator" directory
+-- frontend Component files under site's root director
+-- media OPTIONAL. Component media files, under site's "media" directory
+-- cli OPTIONAL. Component CLI script installed under site's "cli" directory
+-- language OPTIONAL. Language files for your component.
The backend, frontend, media and language directories can have any name you want as they are NOT handled by the installation script. They are defined in your component's XML manifest and it's up to Joomla! to decide what to do with them.
The cli
directory contains command-line scripts which will be copied to your site's "cli" directory. They are typically used to set up CRON jobs for housekeeping or other lengthy operations.
A few notes on XML manifests. Please note that due to one of the myriads of JInstaller's bugs and limitations your component's XML manifest SHOULD be placed in the package's root and MUST begin with a letter before "L". We recommend using the following naming convention to prevent package installation problems due to Joomla! being outright silly in its handling of manifests:
- Components: com_something.xml
- Plugins: plg_foldername_something.xml
- Modules: mod_siteOrAdmin_something.xml
- Libraries: lib_something.xml
- Files: file_something.xml
Using this convention you ensure that when you list all XML manifests in the package and sort them alphabetically the component's manifest will show up first. This is exactly how Joomla! decides which XML manifest to use for installing a package: list all of them, alpha-sort them and pick the first one.
Let's say your component is called Foobar and its Joomla! name is com_foobar. You need to create the file script.foobar.php and place it in the root of your package. The file name and location of the script are extremely important! They are defined in your XML manifest, using a line like this:
<scriptfile>script.com_foobar.php</scriptfile>
You are advised to follow this naming convention and place the script in your package's root to avoid nasty surprises.
Next up, you need to put the following contents in your script file:
<?php
// no direct access
defined('_JEXEC') or die();
// Load FOF if not already loaded
if (!defined('FOF30_INCLUDED') && !@include_once(JPATH_LIBRARIES . '/fof30/include.php'))
{
throw new RuntimeException('This component requires FOF 3.0.');
}
class Com_FoobarInstallerScript extends \FOF30\Utils\InstallScript
{
protected $componentName = 'com_foobar';
protected $componentTitle = 'Foobar Component';
}
Let's analyse this script. We begin by preventing direct access to the file in the standard Joomla! way:
// no direct access
defined('_JEXEC') or die;
Then we have to load FOF. We need to do that because the Installscript which powers our installation script is part of FOF. However FOF might not be already loaded on the site. It does need to be installed. This means that your package file MUST install / update FOF BEFORE the component package is installed.
So here we go loading FOF:
// Load FOF if not already loaded
if (!defined('FOF30_INCLUDED') && !@include_once(JPATH_LIBRARIES . '/fof30/include.php'))
{
throw new RuntimeException('This component requires FOF 3.0.');
}
Next up we define our installation script class for Joomla! to find it:
class Com_FoobarInstallerScript extends \FOF30\Utils\InstallScript
Naming your installation class is EXTREMELY IMPORTANT. If you do not follow the naming convention TO THE LETTER Joomla! will not "see" your installation script. This results to immense amounts of hair pulling as Joomla! throws no error whatsoever when you tell it to use an installation script and it doesn't find one.
The naming is extremely important. The name must begin with the Joomla! name of your component, with the Com and extension name capitalised, i.e. Com_Foobar. Then it must be followed by exactly InstallerScript. Case seems to matter. If you use installerScript, installerscript etc Joomla! may NOT be able to find your installation script. Mind your case!
The final few lines tell the installation script the component name and the human-readable title.
{
protected $componentName = 'com_foobar';
protected $componentTitle = 'Foobar Component';
}
Warning Since Joomla! does not provide a way to track dependencies, FOF uses its own dependency tracking. When you install a component which uses a script extending from FOF's InstallScript class the component is registered as depending on the specific FOF version on installation and unregisters the dependency on uninstallation. For this reason your package file must install FOF before installing the component and uninstall FOF after uninstalling the component.
That said, you can't get away with merely listing FOF's library ZIP file in your package manifest. When you try to install an older version of FOF than the one currently installed the library package's installer will raise an exception. If you try to uninstall it when there are extensions marked as depending on it an exception will be raised as well. This prevents Joomla! from installing / removing the library package when it shouldn't, but the exception bubbles up to the installer infrastructure, canceling your package's installation / uninstallation. This is why you need to use a custom package installation script as shown in the Akeeba Subscriptions repository (links above). Failure to do so may result in your package failing to install or upgrade. If you try to circumvent FOF's installation script and we find it out you will be placed in a very public Hall of Shame list FOREVER. If you're unsure about what you're doing please ask on the mailing list. Alternatively, ask your clients to install the FOF package before installing your extension's package. Either will do just fine and will NOT land you on the Hall of Shame.
All customisation can be done by overriding the protected properties and methods of Installscript. The properties are:
componentName MANDATORY. The component's name, e.g. 'com_foobar'. You absolutely need to set this, otherwise
componentTitle MANDATORY. The component's human readable title, e.g. 'My Foobar Component'.
uninstallation_queue The list of obsolete extra modules and plugins to uninstall on component upgrade / installation. Please note that this IS NOT used when uninstalling the component. The reason of $uninstallation_queue
's existence is a simple way to uninstall obsolete plugins and modules when you update a component. It is an array like this:
protected $uninstallation_queue = array(
// modules => { (folder) => { (module) }* }*
'modules' => array(
'admin' => array(
'adminobsolete'
),
'site' => array()
),
// plugins => { (folder) => { (element) }* }*
'plugins' => array(
'system' => array(
'obsoleteplugin'
),
)
);
The modules
key is an array containing exactly two keys, admin
and site
, both being arrays containing the list of administrator (back-end) and site (front-end) modules to be uninstalled respectively.
Each module definition consists of a single value which is the module name to be uninstalled.
In the example above the adminobsolete
is an administrator module which will be uninstalled when you install or upgrade the component.
The plugins
key is an array containing one or more keys. Each key is the name of a Joomla! plugins folder and its contents is an array containing the list of plugins to uninstall.
Each plugin definition consists of a single value which is the plugin name.
In the example above the plg_system_obsoleteplugin
plugin will be uninstalled whenever the component is installed or updated.
removeFilesFree Obsolete files and folders to remove from the free version only. This is used when you move a feature from the free version of your extension to its paid version ($isPaid
is true). If you don't have such a distinction you can ignore this and use the $removeFilesAllVersion
option instead. The format is:
protected $removeFilesFree = array(
'files' => array(
'administrator/components/com_foobar/helpers/whatever.php'
),
'folders' => array(
'administrator/components/com_foobar/baz'
)
);
The array has exactly two keys. The files key is an array containing a list of files to be removed on installation / update. The folders key is an array containing a list of folders to be recursively removed on installation / update. Files and folders are given as paths relative to the site's root.
removeFilesAllVersions Obsolete files and folders to remove from both paid and free releases. This is used when you refactor code and some files inevitably become obsolete and need to be removed. These files are always removed, no matter what the $isPaid
value is. Its format is the same as removeFilesFree
.
cliScriptFiles A list of all CLI scripts to be copied to the "cli" directory of the site. These are copied from the package directory defined in $cliSourcePath. Its format is a simple array listing the names of the files to be copied.
Note: we recommend using a files
package instead, just like we do in Akeeba Subscriptions.
cliSourcePath The path inside your package where cli scripts are stored. Please remember that this is the path inside your package, NOT the path inside your user's site.
schemaXmlPathRelative Is the schemaXmlPath class variable a relative path? If set to true the schemaXmlPath
variable contains a path relative to the component's back-end directory. If set to false the schemaXmlPath
variable contains an absolute filesystem path. This is used when installing / updating / removing your database tables using the XML schema files.
schemaXmlPath The path where the schema XML files are stored. Its contents depend on the schemaXmlPathRelative
variable above
minimumPHPVersion The minimum PHP version required to install this extension. If it's empty no minimum version check will be performed. You are advised to not set it to a version lower than what FOF requires (the default value of this property).
minimumJoomlaVersion The minimum Joomla! version required to install this extension. If it's empty no minimum version check will be performed. You are advised to not set it to a version lower than what FOF requires (the default value of this property).
maximumJoomlaVersion The maximum Joomla! version this extension can be installed on. If it's empty no maximum version check will be performed. You are advised to enter at least 3.9.99 here, making sure your extension will not installable under Joomla! 4.0. Given the current discussions of what Joomla! 4 will look like it will require a new major version of FOF and a massive rewrite of your components.
isPaid Is this the paid version of the extension? This only determines which files / extensions will be removed. This is strictly optional.
As for the methods you can consult the docblocks in the Installscript class.
FOF (Framework on Framework) and its documentation are Copyright © 2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd.
FOF is Open Source Software, distributed under the GNU General Public License, version 2 of the license, or (at your option) any later version.
The FOF Wiki content is provided under the GNU Free Documentation License, version 1.3 of the license, or (at your option) any later version.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be found on the GNU site.