Key Tip to making a single installer for Joomla 1.5, 2.5 and 3.0 extensions

This is a short tutorial that I have made to share with everyone on how I was able to make a single installer for my Easy Folder Listing module. This installer works on Joomla 1.5, Joomla 2.5 and Joomla 3.0. Now, you may be wondering… “Mike, how did you do that?!” Well, it’s actually quite simple. Let’s me give you a little introduction before we get into the gist of things.

Introduction

The Joomla documentation provides a great tutorial on how to make a single installer that works on Joomla 1.5, 1.6 and 1.7. This can be found here. That tutorial works for Joomla 2.5 as well. However, when Joomla 3.0 came along, it changed two major things the break that tutorial’s applicability to work for all supported Joomla versions. The two main issues are:

  1. Removal of deprecated classes, functions, and constants
  2. Removal of recognition of the root xml tag in the manifest file: <install></install>

There have been some discussion on how to deal with the issue of deprecated classes, functions and constants. Some of these discussions can be found on the Joomla Development Google Group. One such discussion can be found here. However, one very important resource for dealing with the deprecated API can be found in the Joomla documentation. I encourage you to please check that out, because it will help you greatly. It can be found here.

All the above mentioned resources are great, and are all very important for creating a bug-free single installer for all Joomla versions. However, none of them deal with the single issue that Joomla 3 brings to the table and that is that it no longer recognizes the install tag in the manifest file. I provide a work-around fix to this issue in my tutorial.

Problem Analysis

The manifest file for Joomla 1.5 used install as the root element tag. In Joomla 1.6 to 2.5, the manifest file can use either install or extension as the root element tag. So, extensions manifest made for Joomla 2.5 that used an install tag were backward-compatible Joomla 1.5. However, with Joomla 3.0, only extension is recognized as the root element tag in the manifest, thereby breaking backward compatibility to Joomla 1.5.

So, the question is, “How can we overcome this break in backward compatibility in the manifest file?”

Solution

The answer is, “Use two manifest files in the zip installer package!”. You may be wondering, “Huh?! What are you talking about? Two manifest files?! How will that work?” Well, that is what I am going to explain.

One manifest file will be compatible with Joomla 1.5 and 2.5, and the other manifest file will be compatible with Joomla 2.5 and 3.0. The two manifest files are similar, but they differ in three areas:

  1. The root element
  2. Inclusion of script file
  3. Parameters and/or fields

For this example, let’s say we are making a module called, “Easy Module”. Here are the two manifest files:

 

<?xml version="1.0" encoding="utf-8"?> 
<install version="1.5" type="module" client="site" method="upgrade"> 
    <name>MOD_EASYMODULE</name> 
    <author>Michael Gilkes</author> 
    <creationDate>December 2012</creationDate> 
    <copyright>Copyright (C) 2010-2012 Michael Albert Gilkes. All rights reserved.</copyright> 
    <license>http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2</license> 
    <authorEmail>myemail@mydomain.com</authorEmail> 
    <authorUrl>https://www.valorapps.com</authorUrl> 
    <version>1.0</version> 
    <description>MOD_EM_DESCRIPTION</description> 
    <files> 
        <filename module="mod_easymodule">mod_easymodule.php</filename> 
        <filename>index.html</filename> 
        <filename>helper.php</filename> 
        <filename>readme.txt</filename> 
        <folder>tmpl</folder> 
    </files> 
    <media destination="mod_easymodule"> 
        <folder>css</folder> 
        <folder>icons</folder> 
        <folder>images</folder> 
        <folder>scripts</folder> 
    </media> 
    <languages folder="language"> 
        <language tag="en-GB">en-GB/en-GB.mod_easyfolderlisting.ini</language> 
        <language tag="en-GB">en-GB/en-GB.mod_easyfolderlisting.sys.ini</language> 
    </languages> 
    <params> 
        <param name="word" type="text" default="" label="MOD_EM_WORD_LABEL" description="MOD_EM_WORD_DESC" /> 
        <param type="spacer" default="MOD_EM_SPACER" /> 
        <param name="moduleclass_sfx" type="text" default="" label="MOD_EM_SUFFIX_LABEL" description="MOD_EM_SUFFIX_DESC" /> 
    </params> 
    <config> 
        <fields name="params">
            <fieldset name="basic"> 
                <field name="word" type="text" default="" label="MOD_EM_WORD_LABEL" description="MOD_EM_WORD_DESC" />
            </fieldset> 
            <fieldset name="advanced"> 
                <field name="moduleclass_sfx" type="text" label="MOD_EM_SUFFIX_LABEL" description="MOD_EM_SUFFIX_DESC" /> 
            </fieldset> 
        </fields> 
    </config> 
</install>

 

<?xml version="1.0" encoding="utf-8"?> 
<extension version="2.5" type="module" client="site" method="upgrade"> 
    <name>MOD_EASYMODULE</name> 
    <author>Michael Gilkes</author> 
    <creationDate>December 2012</creationDate> 
    <copyright>Copyright (C) 2010-2012 Michael Albert Gilkes. All rights reserved.</copyright> 
    <license>http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2</license> 
    <authorEmail>myemail@mydomain.com</authorEmail> 
    <authorUrl>https://www.valorapps.com</authorUrl> 
    <version>1.0</version> 
    <description>MOD_EM_DESCRIPTION</description> 
    <files> 
        <filename module="mod_easymodule">mod_easymodule.php</filename> 
        <filename>index.html</filename> 
        <filename>helper.php</filename> 
        <filename>readme.txt</filename> 
        <folder>tmpl</folder> 
    </files> 
    <media destination="mod_easymodule"> 
        <folder>css</folder> 
        <folder>icons</folder> 
        <folder>images</folder> 
        <folder>scripts</folder> 
    </media> 
    <languages folder="language"> 
        <language tag="en-GB">en-GB/en-GB.mod_easyfolderlisting.ini</language> 
        <language tag="en-GB">en-GB/en-GB.mod_easyfolderlisting.sys.ini</language> 
    </languages> 
    <!-- Runs on install/uninstall/update; New in 2.5 --> 
    <scriptfile>script.php</scriptfile> 
    <config> 
        <fields name="params"> 
            <fieldset name="basic"> 
                <field name="word" type="text" default="" label="MOD_EM_WORD_LABEL" description="MOD_EM_WORD_DESC" /> 
            </fieldset> 
            <fieldset name="advanced"> 
                <field name="moduleclass_sfx" type="text" label="MOD_EM_SUFFIX_LABEL" description="MOD_EM_SUFFIX_DESC" /> 
            </fieldset> 
        </fields> 
    </config> 
</extension>

With 2 manifest files, we can leverage the way all versions of Joomla find the manifest files in an installer package. What every version of Joomla does is to find every xml file in the zip package, regardless of the name of the file, and then it tests each xml file until it finds the first one it can successfully identify as a manifest file. I deliberately named the Joomla 3 compatible manifest as “_manifest.xml” and the Joomla 1.5 compatibale manifest as “mod_easymodule.xml“. Now, the correct name for the manifest file is “mod_easymodule.xml” for our tutorial example. But, when it comes to searching, Joomla 1.5 will skip _manifest.xml and find mod_easymodule.xml; whereas, Joomla 3 will find _manifest.xml first and ignore mod_easymodule.xml. Joomla 2.5 can find either one, but will most likely find _manifest.xml.

The key to making the _manifest.xml file work for Joomla 3 is the script file that is a new feature addition to Joomla 2.5+. In the script file below, what we will do is to copy the _manifest.xml file into the extension folder and rename it to replace the mod_easymodule.xml file that will have already existed there at the end of an installation/update process.

<?php // No direct access to this file 
defined('_JEXEC') or die('Restricted access'); 

class mod_easymoduleInstallerScript 
{
    function preflight($route, $adapter) {} 

    function install($adapter) {} 

    function update($adapter) {} 

    function uninstall($adapter) {} 
    
    function postflight($route, $adapter) 
    {
        if (stripos($route, 'install') !== false || stripos($route, 'update') !== false) 
        {
            return $this->fixManifest($adapter); 
        }
    }

    private function fixManifest($adapter) 
    {
        $filesource = $adapter->get('parent')->getPath('source').'/_manifest.xml';
        $filedest = $adapter->get('parent')->getPath('extension_root').'/mod_easymodule.xml';
        if (!(JFile::copy($filesource, $filedest)))
        {
            JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_FAIL_COPY_FILE', $filesource, $filedest), JLog::WARNING, 'jerror');

            if (class_exists('JError'))
            {
                JError::raiseWarning(1, 'JInstaller::install: '.JText::sprintf('Failed to copy file to', $filesource, $filedest));
            }
            else
            {
                throw new Exception('JInstaller::install: '.JText::sprintf('Failed to copy file to', $filesource, $filedest));
            }
            return false;
        }
        return true;
    }
}

 

That’s it! You can learn more about script files here and here. This has worked for me in having a single installer for my modules. I am going to use the same principle for my plugins. It should work for components, but I haven’t tried it.

Let me know if this help.

2 comments

wohooooo, u made my day :3 <3 awsome! I knew it all, exept i didn't come come to the idea yay to use the installer to simply rename the file. my lil add to this : either additionally delete the old file ( since u would get nasty errorwarning and extension-remainders when u try to uninstall the extension ) OR do as i do and change the copy function and use the JFile::move -function instead to simply rename the file. Thumbs up :) Lab5 – Webdesign Schweiz
@lab5. Thanks for your comments and contribution. I actually originally thought about deleting the old file (_manifest.xml), but then when I uninstalled the module on Joomla 2.5+, it removed the files without any issue. In Joomla 1.5, the _manifest.xml file is not copied during installation. In regards to using the JFile::move function, I don’t think that would really apply since the source I am copying from is the installation files and not the copy installed in the modules directory. The installation files are stored in a temporary folder. So, it doesn’t matter whether you delete it from there or not.

Leave a Reply to lab5 Cancel Reply