J4.x

Creating a Simple Module

From Joomla! Documentation

Revision as of 12:23, 27 June 2024 by Robbiej (talk | contribs) (Added deprecation notice and link to Joomla Manual)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Other languages:
Deutsch • ‎English • ‎Nederlands • ‎français • ‎italiano • ‎polski • ‎português • ‎Ελληνικά • ‎русский
Stop hand nuvola.svg.png
Warning!

With the move of developer documentation to the Joomla Manual, this page is unlikely to be actively maintained. A similar tutorial is available at Joomla Manual Module Development Tutorial


Joomla! 
4.x
>Tutorial
Creating a Simple Module for Joomla 4.x

This is a tutorial on how to Create a simple module for Joomla Version 4x.

Introduction[edit]

Joomlaǃ 4 provides five types of extensionsː

  • Components
    A component is the main part of the site. A component handles data manipulation as well as input and storage into the database. A component on most sites is the primary focus of the page.
  • Modules
    A module is an add-on to the site that extends the functionality. A module usually occupies a secondary portion of the web page and is not considered the primary focus of a page. It can be displayed on different positions and you can choose on which active menu items it should be displayed. Modules are lightweight and flexible extensions. They are used for small bits of the page that are generally less complex and are able to be seen across different components.
  • Plugins
    A Plugin manipulates output that is already generated by the system. It typically does not run as separate part of the site. It takes data from other sources (i.e. the content) and manipulates this data before displaying. A plugin typically work behind the scenes.
  • Languages
    Probably the most basic extensions are languages. In essence the language package files consist of key/value pairs, which provide the translation of static text strings, assigned within the Joomla! source code.
  • Templates
    A template is basically the design of your Joomla! powered website.

Joomla! 4 is constructed using five different applications:

  • Installation (used for installing Joomla and have to delete after installation)
  • Administrator (Backend - used for managing content)
  • Public or site (Frontend - used for displaying content)
  • CLI (used for accessing Joomla on the command line and for cron jobs)
  • API (web services - used for creating APIs for machine accessible content)

The installation application is used once. The administrator and public are used through the concept of components with modules. Each module has a single entry point located in the modules and accordingly administrator/modules directory. This entry point is called mod_modulename/mod_modulename.php (the mod_ prefix is a historical trace). The entry point for the login module is for example /mod_login/mod_login.php.

Requirements[edit]

You need Joomla! 4.x installation available to use for this tutorial (Download latest release here)

You can download Joomla! 4 at GitHub, on the Developer website or you can create a free website at https://launch.joomla.org.

Creating a Simple Module/Developing a Basic Module[edit]

You can see many examples of modules in the standard Joomla! install. For example:

  • Menus
  • Latest News
  • Login form
  • and many more.

This tutorial will explain how to create a simple module. Through this tutorial you will learn the basic file structure of a Joomlaǃ 4 module. This basic structure can then be expanded to produce more elaborate modules.

File Structure[edit]

There are a few basic files that are used in the standard pattern of module development:

  • mod_foo.php - This file is the main entry point for the module. It will perform any necessary initialization routines, call helper routines to collect any necessary data, and include the template which will display the module output.
  • mod_foo.xml - This file contains information about the module. It defines the files that need to be installed by the Joomla! installer and specifies configuration parameters for the module.
  • tmpl/default.php - This is the module template. This file will take the data collected by mod_foo.php and generate the HTML to be displayed on the page.
  • language/en-GB/mod_foo.ini and language/en-GB/mod_foo.sys.ini- This are the files that provide the text in United Kingdom English.

Creating mod_foo.php[edit]

The mod_foo.php file will perform following tasks:

  • Import the class ModuleHelper to the current scope. We need it later for displaying the output.
  • Include the template to display the output.

The helper class is imported to our current scope at the begin of the file.

use Joomla\CMS\Helper\ModuleHelper;

Last we include the template to display the output via

require ModuleHelper::getLayoutPath('mod_foo', $params->get('layout', 'default'));

Completed mod_foo.php File[edit]

The complete mod_foo.php file is as follows:

<?php
/**
 * @package    [PACKAGE_NAME]
 *
 * @author     [AUTHOR] <[AUTHOR_EMAIL]>
 * @copyright  [COPYRIGHT]
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 * @link       [AUTHOR_URL]
 */

// No direct access to this file
defined('_JEXEC') or die;

use Joomla\CMS\Helper\ModuleHelper;

require ModuleHelper::getLayoutPath('mod_foo', $params->get('layout', 'default'));

Side noteː In Joomla 3x you usually used a line like $moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx'));. You don't need this anymore. See this PRː https://github.com/joomla/joomla-cms/pull/17447.

The one line that we haven’t explained so far is the first line defined('_JEXEC') or die;. This line checks to make sure that this file is being included from the Joomla application. This is necessary to prevent variable injection and other potential security concerns.

Creating tmpl/default.php[edit]

The default.php file is the template which displays the module output.

Completed tmpl/default.php file[edit]

The code for the tmpl/default.php file is as follows:

<?php
/**
 * @package    [PACKAGE_NAME]
 *
 * @author     [AUTHOR] <[AUTHOR_EMAIL]>
 * @copyright  [COPYRIGHT]
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 * @link       [AUTHOR_URL]
 */

// No direct access to this file
defined('_JEXEC') or die;

echo '[PROJECT_NAME]';

An important point to note is that the template file has the same scope as the mod_foo.php file. It means that a variable can be defined in the mod_foo.php file and then used in the template file without any extra declarations or function calls.

Creating mod_foo.xml[edit]

The mod_foo.xml file is the installation file. Most entries are self-explanatory.

Completed mod_foo.xml file[edit]

The code for the mod_foo.xml file is as follows:

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="4.0" client="site" method="upgrade">
    <name>MOD_FOO</name>
    <creationDate>[DATE]</creationDate>
    <author>[AUTHOR]</author>
    <authorEmail>[AUTHOR_EMAIL]</authorEmail>
    <authorUrl>[AUTHOR_URL]</authorUrl>
    <copyright>[COPYRIGHT]</copyright>
    <license>GNU General Public License version 2 or later; see LICENSE.txt</license>
    <version>1.0</version>
    <description>MOD_FOO_XML_DESCRIPTION</description>
    <files>
        <filename module="mod_foo">mod_foo.php</filename>
        <folder>tmpl</folder>
        <folder>language</folder>
        <filename>mod_foo.xml</filename>
    </files>
</extension>

Creating the Language Files[edit]

The files language/en-GB/mod_foo.ini and language/en-GB/mod_foo.sys.ini are used to translate text in the Frontend and in the Backend. Note that the language file structure has been updated in Joomla 4, and language prefixes on the individual files in a language folder are no longer required.

The code for language/en-GB/mod_foo.sys.ini is as follows:

MOD_FOO="[PROJECT_NAME]"
MOD_FOO_XML_DESCRIPTION="Foo Module"

The code for language/en-GB/mod_foo.ini is as follows:

MOD_FOO="[PROJECT_NAME]"
MOD_FOO_XML_DESCRIPTION="Foo Module"

The .sys.ini file is used to translate the description of the extension upon installation, where as the .ini file is used to translate the remaining strings and the description when viewing your extension.

More information about language files can be found here.

Test Your Module[edit]

Now you can zip all files and install them via the Joomla Extension Manager.
After that you can choose your module in the module manager, when you create a new site module.

Moduletutorial1-en.png
Moduletutorial2-en.png

In the Frontend, you will see your module like displayed in the next image.

Moduletutorial3-en.png

Conclusion[edit]

Module development for Joomla is a fairly simple, straightforward process. Using the techniques described in this tutorial, an endless variety of modules can be developed with little hassle.

You can find boilerplates hereː

The sample files for this Tutorial can be found hereː

Add a Helper Class Using Namespaces[edit]

Requirements[edit]

You need Joomla! 4.x for this tutorial.

Namespaces[edit]

With PHP 5.3, the namespaces came into their own. In other programming languages for a long time in use, these small structures now also help us with the clarity of our code.

Namespaces are separate areas in which certain logical things (in our case, classes, interfaces, functions, and constants) can live. These areas provide encapsulation of the code and prevent name conflicts.

Let's take a look how to use them in Joomla 4. We use the helper file for this.

File Structure[edit]

We will create/change the following files:

  • Helper/FooHelper.php - This is the file we use here as an example. We have to create it.
  • mod_foo.php - In this file, we will mainly load the namespace.
  • tmpl/default.php - In this file, we will demonstrate how the data of a helper can be displayed.
  • mod_foo.xml - We create a new directory with a new file. This must be installed during the installation. For this we have to specify them in this file.

Creating Helper/FooHelper.php[edit]

Our new helper class should belong to a namespace. We achieve this with the following code. It is important, that this line is at the beginning of the file.

namespace Joomla\Module\Foo\Site\Helper;

Then we create a simple class with a simple method. Of course you can do a lot more here. Take a look at the Joomla core methods. Here are many examples. They show you first-hand what options you have.

Completed Helper/FooHelper.php[edit]

The complete FooHelper.php file is as follows:

<?php
/**
 * @package     Joomla.Site
 * @subpackage  mod_foo
 *
 * @copyright   Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

namespace Joomla\Module\Foo\Site\Helper;

// No direct access to this file
defined('_JEXEC') or die;

/**
 * Helper for mod_foo
 *
 * @since  4.0
 */
class FooHelper
{
	/**
	 * Retrieve foo test
	 *
	 * @param   Registry        $params  The module parameters
	 * @param   CMSApplication  $app     The application
	 *
	 * @return  array
	 */
	public static function getText()
	{
		return 'FooHelpertest';
	}
}

Editing mod_foo.php[edit]

Our new helper class is imported to our current scope at the beginning of the file.

use Joomla\Module\Foo\Site\Helper\FooHelper;

Last use the helper file for testing if it is loaded correctlyː

$test  = FooHelper::getText($params, $app);

Completed mod_foo.php file[edit]

The complete mod_foo.php file is as follows:

<?php
/**
 * @package    [PACKAGE_NAME]
 *
 * @author     [AUTHOR] <[AUTHOR_EMAIL]>
 * @copyright  [COPYRIGHT]
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 * @link       [AUTHOR_URL]
 */

// No direct access to this file
defined('_JEXEC') or die;

use Joomla\CMS\Helper\ModuleHelper;
use Joomla\Module\Foo\Site\Helper\FooHelper;

$test  = FooHelper::getText();

require ModuleHelper::getLayoutPath('mod_foo', $params->get('layout', 'default'));

Editing tmpl/default.php[edit]

In this file you make only a small change to demonstrate in the Frontend that your helper file is working properly. You only add the value of the variable at the end of the current output.

echo '[PROJECT_NAME]' . $test;

Completed tmpl/default.php[edit]

The complete tmpl/default.php file is as follows:

<?php
/**
 * @package    [PACKAGE_NAME]
 *
 * @author     [AUTHOR] <[AUTHOR_EMAIL]>
 * @copyright  [COPYRIGHT]
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 * @link       [AUTHOR_URL]
 */

// No direct access to this file
defined('_JEXEC') or die;

echo '[PROJECT_NAME]' . $test;

Editing mod_foo.xml[edit]

First you have to add a line, so that the namespace is set automatically in Joomla. After this change, you have to re-install your module. A simple change in an already installed module is not enough. If you are doing local development you can also delete the files libraries/autoload_psr4.php and it will automatically be re-created. After inserting and installing, the namespace is known by the loader JPATH_LIBRARIES . '/autoload_psr4.php'.

<namespace>Joomla\Module\Foo</namespace>

Joomla! should copy your helper file when installing the module. So Joomla! needs to know your helper file. For this, you need to add the following line to your XML file.

<folder>Helper</folder>

Completed mod_foo.xml[edit]

The complete mod_foo.xml file is as follows:

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="4.0" client="site" method="upgrade">
    <name>MOD_FOO</name>
    <creationDate>[DATE]</creationDate>
    <author>[AUTHOR]</author>
    <authorEmail>[AUTHOR_EMAIL]</authorEmail>
    <authorUrl>[AUTHOR_URL]</authorUrl>
    <copyright>[COPYRIGHT]</copyright>
    <license>GNU General Public License version 2 or later; see LICENSE.txt</license>
    <version>1.0</version>
    <description>MOD_FOO_XML_DESCRIPTION</description>
    <namespace>Joomla\Module\Foo</namespace>
    <files>
        <filename module="mod_foo">mod_foo.php</filename>
        <folder>tmpl</folder>
        <folder>Helper</folder>
        <folder>language</folder>
        <filename>mod_foo.xml</filename>
    </files>
</extension>

Test Your Module[edit]

Now you can zip all files and install them via the Joomla Extension Manager. After that you can choose your module in the module manager, when you create a new site module.

In the Frontend you will see your module like displayed in the next image. The text from your helper file is displayed.

Moduletutorial23-en.png

Conclusion[edit]

As you can see, once you get a bit into the namespaces, they are not that complicated anymore. In big projects they can bring a lot of benefits. However, we should plan namespaces, as otherwise it will soon be more time-consuming.

You can find boilerplates hereː

The sample files for this Tutorial can be found hereː

Customizationː Add Parameters Via Form Fields[edit]

Requirements[edit]

You need Joomla! 4.x for this tutorial.

Customization with Form Fields and Parameters[edit]

Form fields give a great deal of customization in Joomla and for modules are the sole way of allowing the user to tweak the module to the needs of their site.

In this case we are going to extend our previous example using a URL field for inserting a domain that we can use as link in the front end. To allow this to happen we will use the URL Form Field type.

After that, we insert parameters that allow to use standard functionality of Joomla.

Let's take a look on how to use them in Joomla 4.

File Structure[edit]

We will change the following files:

  • mod_foo.xml - This is the file where we add the fields.
  • tmpl/default.php - In this file demonstrate how the data of a field can be used.
  • language/en-GB/en-GB.mod_foo.ini - Here we use a language string so that the field can be labeled correctly in different languages.

Editing mod_foo.xml[edit]

First we set a custom parameter.

<field
    name="domain"
    type="url"
    label="MOD_FOO_FIELD_URL_LABEL"
    filter="url"
/>

Then we insert Joomla default fields, so that we can use cache, moduleclass-suffix and layouts.

<field
    name="layout"
    type="modulelayout"
    label="JFIELD_ALT_LAYOUT_LABEL"
    class="custom-select"
/>

<field
    name="moduleclass_sfx"
    type="textarea"
    label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL"
    rows="3"
/>

<field
    name="cache"
    type="list"
    label="COM_MODULES_FIELD_CACHING_LABEL"
    default="0"
>
    <option value="1">JGLOBAL_USE_GLOBAL</option>
    <option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option>
</field>

<field
    name="cache_time"
    type="number"
    label="COM_MODULES_FIELD_CACHE_TIME_LABEL"
    default="0"
/>

<field
    name="cachemode"
    type="hidden"
    default="itemid"
>
    <option value="itemid"></option>
</field>

Completed mod_foo.xml[edit]

The complete mod_foo.xml file is as follows:

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="4.0" client="site" method="upgrade">
    <name>MOD_FOO</name>
    <creationDate>[DATE]</creationDate>
    <author>[AUTHOR]</author>
    <authorEmail>[AUTHOR_EMAIL]</authorEmail>
    <authorUrl>[AUTHOR_URL]</authorUrl>
    <copyright>[COPYRIGHT]</copyright>
    <license>GNU General Public License version 2 or later; see LICENSE.txt</license>
    <version>1.0</version>
    <description>MOD_FOO_XML_DESCRIPTION</description>
    <namespace>Joomla\Module\Foo</namespace>
    <files>
        <filename module="mod_foo">mod_foo.php</filename>
        <folder>tmpl</folder>
        <folder>Helper</folder>
        <folder>language</folder>
        <filename>mod_foo.xml</filename>
    </files>
    <config>
        <fields name="params">
            <fieldset name="basic">
                <field
                    name="domain"
                    type="url"
                    label="MOD_FOO_FIELD_URL_LABEL"
                    filter="url"
                />
            </fieldset>
            <fieldset name="advanced">
                <field
                    name="layout"
                    type="modulelayout"
                    label="JFIELD_ALT_LAYOUT_LABEL"
                    class="custom-select"
                />
                <field
                    name="moduleclass_sfx"
                    type="textarea"
                    label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL"
                    rows="3"
                />
                <field
                    name="cache"
                    type="list"
                    label="COM_MODULES_FIELD_CACHING_LABEL"
                    default="0"
                >
                    <option value="1">JGLOBAL_USE_GLOBAL</option>
                    <option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option>
                </field>
                <field
                    name="cache_time"
                    type="number"
                    label="COM_MODULES_FIELD_CACHE_TIME_LABEL"
                    default="0"
                />
                <field
                    name="cachemode"
                    type="hidden"
                    default="itemid"
                >
                    <option value="itemid"></option>
                </field>
            </fieldset>
        </fields>
    </config>
</extension>

Editing tmpl/default.php[edit]

We can use the value of the parameter for creating a hyperlink in the Frontend. We can access the value via the variable $params.

$domain = $params->get('domain', 'https://www.joomla.org');

Later we set use this value for creating the hyperlink.

<a href="<?php echo $domain; ?>">
	<?php echo '[PROJECT_NAME]' . $test; ?>
</a>

Completed tmpl/default.php file[edit]

The complete tmpl/default.php file is as follows:

<?php
/**
 * @package    [PACKAGE_NAME]
 *
 * @author     [AUTHOR] <[AUTHOR_EMAIL]>
 * @copyright  [COPYRIGHT]
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 * @link       [AUTHOR_URL]
 */

// No direct access to this file
defined('_JEXEC') or die;

$domain = $params->get('domain', 'https://www.joomla.org');
?>

<a href="<?php echo $domain; ?>">
	<?php echo '[PROJECT_NAME]' . $test; ?>
</a>

Editing language/en-GB/en-GB.mod_foo.ini[edit]

Here we can specify the text for the English version of the field label.

MOD_FOO_FIELD_URL_LABEL="Url"

Completed language/en-GB/en-GB.mod_foo.ini[edit]

The complete language/en-GB/en-GB.mod_foo.ini file is as follows:

MOD_FOO="[PROJECT_NAME]"
MOD_FOO_XML_DESCRIPTION="Foo Module"
MOD_FOO_FIELD_URL_LABEL="Url"

Test Your Module[edit]

Now you can zip all files and install them via the Joomla Extension Manager. After that you can choose your module in the module manager, when you create a new site module.

In the Backend, you will see your module like displayed in the next image.

In the basic tab, you will see the custom field where you can insert a domain. The text for the label is fetched from the language file.

Moduletutorial31-en.png

In the advanced tab, you will see all default options except the cache mode because of this is a hidden field.

Moduletutorial32-en.png

In the Frontend, you will see your module like displayed in the next image. The text form your helper file is displayed and you should see a hyperlink.

Moduletutorial33-en.png

Conclusion[edit]

Form fields give the user an easy way to customize the module to their sites settings. This allows the modules scope to be increased.

You can find boilerplates hereː

The sample files for this Tutorial can be found hereː

See this issue for possible future changes:

Use Install, Update and Uninstall Script[edit]

Requirements[edit]

You need Joomla! 4.x for this tutorial.

Scripts[edit]

Installing, updating and uninstalling a module may require additional operations that cannot be achieved by the basic operations described in the main XML file. Joomla offers a new approach to solve this problem. It consists in using a PHP script file containing a class using five methods:

  • preflight which is executed before install and update
  • install
  • update
  • uninstall
  • postflight which is executed after install and update

Let's take a look how to use them in Joomla 4. We use the helper file for this.

File Structure[edit]

We will create/change the following files:

  • script.php - This is the file we use here as an example. We have to create it.
  • language/en-GB/en-GB.mod_foo.sys.ini - In this file we will add text.
  • mod_foo.xml - We create a new file. This must be installed during the installation. For this we have to specify it in this file.

Creating script.php[edit]

Writing an extension script consists in declaring a class whose name is mod_ModuleNameInstallerScript with these 5 methods. See the comments in the file for more information. In this comments I explain when a method is called.

In this example, I only use text to show when which method will be executed. In addition, I show you how to check the minimum requirements. Of course you can do much more. For example, you can delete files that are no longer needed in a new version of your module. This can be seen in the file. Another idea for this file is to create sample content, to show a success message with the current installed version number or you can redirect after a successful installation to the page with the module settings.

Completed script.php[edit]

The complete script.php file is as follows:

<?php
/**
 * @package    [PACKAGE_NAME]
 *
 * @author     [AUTHOR] <[AUTHOR_EMAIL]>
 * @copyright  [COPYRIGHT]
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 * @link       [AUTHOR_URL]
 */

// No direct access to this file
defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
use Joomla\CMS\Log\Log;

/**
 * Script file of Foo module
 */
class mod_fooInstallerScript {

    /**
     * Extension script constructor.
     *
     * @return  void
     */
    public function __construct() {
        $this->minimumJoomla = '4.0';
        $this->minimumPhp = JOOMLA_MINIMUM_PHP;
    }

    /**
     * Method to install the extension
     *
     * @param   InstallerAdapter  $parent  The class calling this method
     *
     * @return  boolean  True on success
     */
    function install($parent) {
        echo Text::_('MOD_FOO_INSTALLERSCRIPT_INSTALL');

        return true;
    }

    /**
     * Method to uninstall the extension
     *
     * @param   InstallerAdapter  $parent  The class calling this method
     *
     * @return  boolean  True on success
     */
    function uninstall($parent) {
        echo Text::_('MOD_FOO_INSTALLERSCRIPT_UNINSTALL');

        return true;
    }

    /**
     * Method to update the extension
     *
     * @param   InstallerAdapter  $parent  The class calling this method
     *
     * @return  boolean  True on success
     */
    function update($parent) {
        echo Text::_('MOD_FOO_INSTALLERSCRIPT_UPDATE');

        return true;
    }

    /**
     * Function called before extension installation/update/removal procedure commences
     *
     * @param   string            $type    The type of change (install, update or discover_install, not uninstall)
     * @param   InstallerAdapter  $parent  The class calling this method
     *
     * @return  boolean  True on success
     */
    function preflight($type, $parent) {
        // Check for the minimum PHP version before continuing
        if (!empty($this->minimumPhp) && version_compare(PHP_VERSION, $this->minimumPhp, '<')) {
            Log::add(Text::sprintf('JLIB_INSTALLER_MINIMUM_PHP', $this->minimumPhp), Log::WARNING, 'jerror');

            return false;
        }

        // Check for the minimum Joomla version before continuing
        if (!empty($this->minimumJoomla) && version_compare(JVERSION, $this->minimumJoomla, '<')) {
            Log::add(Text::sprintf('JLIB_INSTALLER_MINIMUM_JOOMLA', $this->minimumJoomla), Log::WARNING, 'jerror');

            return false;
        }

        echo Text::_('MOD_FOO_INSTALLERSCRIPT_PREFLIGHT');
        echo $this->minimumJoomla . ' ' . $this->minimumPhp;

        return true;
    }

    /**
     * Function called after extension installation/update/removal procedure commences
     *
     * @param   string            $type    The type of change (install, update or discover_install, not uninstall)
     * @param   InstallerAdapter  $parent  The class calling this method
     *
     * @return  boolean  True on success
     */
    function postflight($type, $parent) {
        echo Text::_('MOD_FOO_INSTALLERSCRIPT_POSTFLIGHT');

        return true;
    }
}

Editing language/en-GB/en-GB.mod_foo.sys.ini[edit]

There is not much to explain here. Write the text for the translation into this file.

Completed language/en-GB/en-GB.mod_foo.sys.ini file[edit]

The complete language/en-GB/en-GB.mod_foo.sys.ini file is as follows:

MOD_FOO="[PROJECT_NAME]"
MOD_FOO_XML_DESCRIPTION="Foo Module"
MOD_FOO_INSTALLERSCRIPT_PREFLIGHT="<p>Anything here happens before the installation/update/uninstallation of the module</p>"
MOD_FOO_INSTALLERSCRIPT_UPDATE="<p>The module has been updated</p>"
MOD_FOO_INSTALLERSCRIPT_UNINSTALL="<p>The module has been uninstalled</p>"
MOD_FOO_INSTALLERSCRIPT_INSTALL="<p>The module has been installed</p>"
MOD_FOO_INSTALLERSCRIPT_POSTFLIGHT="<p>Anything here happens after the installation/update/uninstallation of the module</p>"

Editing mod_foo.xml[edit]

You have to add a line, so that the script is called automatically in Joomla.

<scriptfile>script.php</scriptfile>

Completed mod_foo.xml[edit]

The complete mod_foo.xml file is as follows:

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="4.0" client="site" method="upgrade">
    <name>MOD_FOO</name>
    <creationDate>[DATE]</creationDate>
    <author>[AUTHOR]</author>
    <authorEmail>[AUTHOR_EMAIL]</authorEmail>
    <authorUrl>[AUTHOR_URL]</authorUrl>
    <copyright>[COPYRIGHT]</copyright>
    <license>GNU General Public License version 2 or later; see LICENSE.txt</license>
    <version>1.0</version>
    <description>MOD_FOO_XML_DESCRIPTION</description>
    <namespace>Joomla\Module\Foo</namespace>
    <scriptfile>script.php</scriptfile>
    <files>
        <filename module="mod_foo">mod_foo.php</filename>
        <folder>tmpl</folder>
        <folder>Helper</folder>
        <folder>language</folder>
        <filename>mod_foo.xml</filename>
    </files>
    <config>
        <fields name="params">
            <fieldset name="basic">
                <field
                    name="domain"
                    type="url"
                    label="MOD_FOO_FIELD_URL_LABEL"
                    filter="url"
                />
            </fieldset>
            <fieldset name="advanced">
                <field
                    name="layout"
                    type="modulelayout"
                    label="JFIELD_ALT_LAYOUT_LABEL"
                    class="custom-select"
                />
                <field
                    name="moduleclass_sfx"
                    type="textarea"
                    label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL"
                    rows="3"
                />
                <field
                    name="cache"
                    type="list"
                    label="COM_MODULES_FIELD_CACHING_LABEL"
                    default="0"
                >
                    <option value="1">JGLOBAL_USE_GLOBAL</option>
                    <option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option>
                </field>
                <field
                    name="cache_time"
                    type="number"
                    label="COM_MODULES_FIELD_CACHE_TIME_LABEL"
                    default="0"
                />
                <field
                    name="cachemode"
                    type="hidden"
                    default="itemid"
                >
                    <option value="itemid"></option>
                </field>
            </fieldset>
        </fields>
    </config>
</extension>

Test Your Module[edit]

Now you can zip all files and install them via the Joomla Extension Manager. Immediately after the installation, you will see the following information. This you had entered in the script so.

Moduletutorial14-en.png

Conclusion[edit]

As you can see, Joomla offers you a lot to make your extension easy to use - right from the start.

You can find boilerplates hereː

The sample files for this Tutorial can be found hereː

Use Joomla Updaterː Adding Auto Update[edit]

Requirements[edit]

You need Joomla! 4.x for this tutorial.

Joomla Updater[edit]

The first thing to do is to read the Managing Component Upgrades with Joomla 2.5 - Part 1 tutorial to give an idea of how the upgrade process works in Joomlaǃ. Whilst written for 2.5 the process hasn't changed. Also read Deploying an update server - this is what we'll be implementing in this tutorial.

File Structure[edit]

We will create/change the following files:

  • mod_foo.xml - The only way to update our existing module is to add in a update server - for example http://www.example.com/foo_update.xml - into the xml file.
  • foo_update.xml - Then we have to create the XML file for the update server at http://www.example.com/foo_update.xml to let Joomla know an update is available.

Editing mod_foo.xml[edit]

To add our update server, we need to insert the following lines in your XML-Fileː

<updateservers>
    <server type="extension" priority="1" name="[PROJECT_NAME]">https://www.example.com/mod_foo.xml</server>
</updateservers>

Completed mod_foo.xml[edit]

The complete mod_foo.xml file is as follows:

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="4.0" client="site" method="upgrade">
    <name>MOD_FOO</name>
    <creationDate>[DATE]</creationDate>
    <author>[AUTHOR]</author>
    <authorEmail>[AUTHOR_EMAIL]</authorEmail>
    <authorUrl>[AUTHOR_URL]</authorUrl>
    <copyright>[COPYRIGHT]</copyright>
    <license>GNU General Public License version 2 or later; see LICENSE.txt</license>
    <version>1.0</version>
    <description>MOD_FOO_XML_DESCRIPTION</description>
    <namespace>Joomla\Module\Foo</namespace>
    <files>
        <filename module="mod_foo">mod_foo.php</filename>
        <folder>tmpl</folder>
        <folder>Helper</folder>
        <folder>language</folder>
        <filename>mod_foo.xml</filename>
    </files>
    <updateservers>
        <server type="extension" priority="1" name="[PROJECT_NAME]">https://www.example.com/mod_foo.xml</server>
    </updateservers>
    <config>
        <fields name="params">
            <fieldset name="basic">
                <field
                    name="domain"
                    type="url"
                    label="MOD_FOO_FIELD_URL_LABEL"
                    filter="url"
                />
            </fieldset>
            <fieldset name="advanced">
                <field
                    name="layout"
                    type="modulelayout"
                    label="JFIELD_ALT_LAYOUT_LABEL"
                    class="custom-select"
                />
                <field
                    name="moduleclass_sfx"
                    type="textarea"
                    label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL"
                    rows="3"
                />
                <field
                    name="cache"
                    type="list"
                    label="COM_MODULES_FIELD_CACHING_LABEL"
                    default="0"
                >
                    <option value="1">JGLOBAL_USE_GLOBAL</option>
                    <option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option>
                </field>
                <field
                    name="cache_time"
                    type="number"
                    label="COM_MODULES_FIELD_CACHE_TIME_LABEL"
                    default="0"
                />
                <field
                    name="cachemode"
                    type="hidden"
                    default="itemid"
                >
                    <option value="itemid"></option>
                </field>
            </fieldset>
        </fields>
    </config>
</extension>

Now that Joomlaǃ is searching for updates to our extension, let's create one to test our process. First we need to create the file foo_update.xml. So far we have only described the update server. We do not know yet if there is an update. In the file foo_update.xml we indicate when a new version is published and where it can be downloaded.

Creating foo_update.xml[edit]

Now we have to create the XML file at http://www.example.com/foo_update.xml to let Joomla know an update is available.

Completed foo_update.xml[edit]

The complete foo_update.xml file is as follows:

<?xml version="1.0" ?>
<updates>
    <update>
        <name>Foo</name>
        <description>This is mod_foo 1.0.1</description>
        <element>mod_foo</element>
        <type>module</type>
        <version>1.0.1</version>
        <downloads>
            <downloadurl type="full" format="zip">http://www.example.com/mod_foo_101.zip</downloadurl>
        </downloads>
        <maintainer>Joomla</maintainer>
        <maintainerurl>http://www.example.com</maintainerurl>
        <targetplatform name="joomla" version="4.0"/>
        <client>site</client>
    </update>
</updates>

After uploading this file to the address https://www.example.com/mod_foo.xml the update will be displayed in the Joomla Backend.

Test Your Module Update[edit]

Create a copy of the module as it is now. Then let's update the version number to 1.0.1. Now you can zip all files. After that you should load your zip to the URL http://www.example.com/mod_foo_101.zip. Now you can update your module via the Joomla Updater.

Commercial Modules[edit]

Note that in our files we have linked to the extensions updates xml file. And from that xml file we have a location for the zip of the module. This means that if someone was to track this backwards they could find the physical source of your modules zip file. If you don't do like this, you can find a solution in this PRː https://github.com/joomla/joomla-cms/pull/15185 .

Conclusion[edit]

With the Joomlaǃ updater, you can easily reach all users and tell them that there is a new version. Even the update itself is easy.

Each extension should use an update server--especially for security reasons.

You can find boilerplates hereː

The sample files for this Tutorial can be found hereː