Developing an MVC Component/Adding an update server
From Joomla! Documentation
Articles in this Series
This is a multiple-article series of tutorials on how to develop a Model-View-Controller Component for Joomla! Version.
Begin with the Introduction, and navigate the articles in this series by using the navigation button at the bottom or the box to the right (the Articles in this series).
This tutorial is part of the Developing an MVC Component for Joomla! 3.2 tutorial. You are encouraged to read the previous parts of the tutorial before reading this.
In this part, we will cover the various aspects of setting up an update server for our helloworld component.
A video accompanying this step is available at Adding an Update Server.
Updating Joomla extensions via an update server is a two step process:
- finding the updates available for the installed extensions
- selecting an update and installing it.
Typically this is done by the administrator via the Extensions / Manage / Update page.
- You click on Find Updates to find the updates available
- You mark the checkbox of each update you want to install and click on Update.
In this step we enable our Helloworld component to be updated in this way.
Each Joomla extension which is updated via an update server has a URL associated with it which points to an XML file containing details of the updates available. This file could be hosted on the extension developer's own website, for example. If you go to Extensions / Manage / Update Sites you will see this URL in the Update Site column, and you can click on those URLs to see the format of the XML files. (Some of these XML files may be of type "collection" where the first XML element is <extensionset>, and these are described towards the end of this tutorial, but for now we're concentrating on the type "extension" where the first XML element is <updates>).
The XML file (described more fully below) contains details of what updates are available for that extension, including any restrictions (eg you have to be running a certain Joomla version to be able to use it), and the URL of the zip file containing the new version of the extension. You tell Joomla the URL of the XML file for your extension within the manifest file (helloworld.xml), eg
<updateservers> <server type="extension" name="Helloworld Updates">http://myDeveloperSite/helloworld-updates/updates.xml</server> </updateservers>
Below is a basic update XML file
<updates> <update> <name>Helloworld component</name> <description>Helloworld component for Joomla MVC tutorial</description> <element>com_helloworld</element> <type>component</type> <version>1.0.0</version> <downloads> <downloadurl type="full" format="zip">http://myDeveloperSite/helloworld-updates/helloworld-1-0-0.zip</downloadurl> </downloads> <targetplatform name="joomla" version="3." /> <php_minimum>7.1</php_minimum> </update> </updates>
Note that it has
- basic information about the component – eg name, version
- a link to the zip file for that update
- restrictions – for Joomla versions 3.2 to 3.9 only, and at least PHP version 7.1
Whenever an administrator clicks on the Find Updates button, Joomla sends HTTP requests to each of the URLs of these update servers to retrieve the XML files. It parses each XML file,
- ensures it's properly formed XML
- compares the version of the update with the version of the extension currently running
- checks any restrictions (Joomla versions, PHP versions, database versions) with what is currently running.
If it finds it's a valid update for this website, then it inserts a record into the "updates" table in the database. (You'll find at most 1 update for each extension, because if there are several possible then Joomla will store only the most recent valid version, ie with the highest version number).
Once an update has been inserted into the "updates" table it is visible to the administrator in the Extension / Manage / Update page. After checking the checkbox and clicking the Update button Joomla will
- once again send an HTTP request to the URL of the update XML file
- parse the XML file and ensure that conditions for installing that version are still met
- send an HTTP request to the URL of the update zip file, storing the file received in the HTTP response in its /tmp directory
- proceed to install the new version from the downloaded zip file.
In this tutorial step we will update our helloworld extension to use an update server. We'll also set up the server files so that you can verify that the update process works ok. To do this you'll need to configure part of your development area to act as the update server. This basically means creating a directory below the root directory serviced by your web server, and including the update XML file etc in it. For example, I have a folder /helloworld which contains my Joomla instance, so that to access the site I put the URL http://localhost/helloworld/index.php into the browser. For the update server I created a folder /helloworld-updates at the same level as /helloworld, and put the updates.xml file into that folder. I can then access the XML file by putting the URL http://localhost/helloworld-updates/updates.xml into the browser. You'll need to do something similar in your own environment, and verify that the URL is correct by accessing the XML file through your browser.
The only change we need to make to our helloworld component is to include the update server inside the manifest file. Once updated, zip up the component as usual and install it on your Joomla instance.
<?xml version="1.0" encoding="utf-8"?> <extension type="component" version="3.0" method="upgrade"> <name>COM_HELLOWORLD</name> <!-- The following elements are optional and free of formatting constraints --> <creationDate>January 2018</creationDate> <author>John Doe</author> <authorEmail>email@example.com</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>0.0.33</version> <!-- The description is optional and defaults to the name --> <description>COM_HELLOWORLD_DESCRIPTION</description> <!-- Runs on install/uninstall/update; New in 2.5 --> <scriptfile>script.php</scriptfile> <install> <!-- Runs on install --> <sql> <file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file> </sql> </install> <uninstall> <!-- Runs on uninstall --> <sql> <file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file> </sql> </uninstall> <update> <!-- Runs on update; New since J2.5 --> <schemas> <schemapath type="mysql">sql/updates/mysql</schemapath> </schemas> </update> <!-- Site Main File Copy Section --> <!-- Note the folder attribute: This attribute describes the folder to copy FROM in the package to install therefore files copied in this section are copied from /site/ in the package --> <files folder="site"> <filename>index.html</filename> <filename>helloworld.php</filename> <filename>controller.php</filename> <filename>router.php</filename> <folder>controllers</folder> <folder>views</folder> <folder>models</folder> <folder>helpers</folder> </files> <languages folder="site/language"> <language tag="en-GB">en-GB/en-GB.com_helloworld.ini</language> <language tag="fr-FR">fr-FR/fr-FR.com_helloworld.ini</language> </languages> <media destination="com_helloworld" folder="media"> <filename>index.html</filename> <folder>images</folder> <folder>js</folder> <folder>css</folder> </media> <administration> <!-- Administration Menu Section --> <menu link='index.php?option=com_helloworld' img="../media/com_helloworld/images/tux-16x16.png">COM_HELLOWORLD_MENU</menu> <!-- Administration Main File Copy Section --> <!-- Note the folder attribute: This attribute describes the folder to copy FROM in the package to install therefore files copied in this section are copied from /admin/ in the package --> <files folder="admin"> <!-- Admin Main File Copy Section --> <filename>index.html</filename> <filename>config.xml</filename> <filename>helloworld.php</filename> <filename>controller.php</filename> <filename>access.xml</filename> <!-- SQL files section --> <folder>sql</folder> <!-- tables files section --> <folder>tables</folder> <!-- models files section --> <folder>models</folder> <!-- views files section --> <folder>views</folder> <!-- controllers files section --> <folder>controllers</folder> <!-- helpers files section --> <folder>helpers</folder> <!-- layout files section --> <folder>layouts</folder> </files> <languages folder="admin/language"> <language tag="en-GB">en-GB/en-GB.com_helloworld.ini</language> <language tag="en-GB">en-GB/en-GB.com_helloworld.sys.ini</language> <language tag="fr-FR">fr-FR/fr-FR.com_helloworld.ini</language> <language tag="fr-FR">fr-FR/fr-FR.com_helloworld.sys.ini</language> </languages> </administration> <updateservers> <!-- Change the URL below to match that of your own update XML file --> <server type="extension" name="Helloworld Updates">http://localhost/helloworld-updates/updates.xml</server> </updateservers> </extension>
Update Server Files
We're going to put 3 files into the directory which we're using to act as the update server, ie into the /helloworld-updates folder, or wherever you have decided to use. The 3 files are:
- the updates.xml file
- an html file which is an information file for the latest version
- a zip file for the update.
For security purposes you should also add the usual blank index.html file as well. The updates.xml file is below. You should change the infourl and downloadurl to suit your environment, and set values for the targetplatform, php_minimum and supported_databases as you wish.
<updates> <update> <name>Helloworld component</name> <description>Helloworld component for Joomla MVC tutorial</description> <element>com_helloworld</element> <type>component</type> <version>1.0.0</version> <infourl>http://localhost/helloworld-updates/info-1-0-0.html</infourl> <downloads> <downloadurl type="full" format="zip">http://localhost/helloworld-updates/helloworld-1-0-0.zip</downloadurl> </downloads> <tags> <tag>stable</tag> </tags> <targetplatform name="joomla" version="3." /> <php_minimum>5.3</php_minimum> <supported_databases mysql="5.6.19"></supported_databases> </update> </updates>
You can find definitions of the elements of this XML structure at Deploying an Update Server, but note that the attributes min_dev_level and max_dev_level are marked as deprecated in the current (3.9) Joomla code, to be removed in Joomla 4. The information file is just a basic html document, which you can modify as you wish. Its filename must match what is specified in the <infourl> tag above.
<!DOCTYPE html> <html> <head> <title>Helloworld update</title> </head> <body> <h1>Update to version 1.0.0</h1> </body> </html>
Finally create a store a zip file for the new version. As a minimum you need to update the version in the manifest file, and you may wish to make another change which is visible when you visit the site.
- Update the manifest file (helloworld.xml) to set the version line to <version>1.0.0</version>
- Create a zip file of the helloworld component
- Copy the zip file into your update server directory. Its name must match what is specified in the <downloadurl> tag (helloworld-1-0-0.zip above).
Testing the Update Server
To test your update server do the following:
- log in to the backend of your site using an admin account
- go to Extensions / Manage / Update
- click on Find Updates – your helloworld component should appear as an update. (It may already be shown, because when you display the admin control panel it issues an ajax request which initiates the find updates process).
- click on the checkbox next to the helloworld component, and click on Update
- go to Extensions / Manage / Manage and find the helloworld component. Its version should now be 1.0.0 (or whatever version you updated to).
(For info, using phpmyadmin you can change the existing version number of the helloworld component by finding the appropriate record in the extensions table, and updating the version number within the json string in the manifest_cache field.)
Up to now we've been considering the server type="extension", but Joomla also has a server type="collection". The purpose of this type is to allow you to have a collection of different update XML files. You would use a "collection" type if, for example,
- your extension is a package and you want to allow users to update the package components individually
- you want to have different update XML files for different versions of Joomla.
Joomla languages use a collection type. If you have several languages installed and go to Extensions / Manage / Update Sites then you can see that all the languages have the same update site URL pointing to something like https://update.joomla.org/language/translationlist_3.xml . If you open that XML file then you see all the details URLs which are the update XML files of the individual languages, and which can be installed via the Extensions / Manage / Install Languages page.
Joomla core also uses a collection type. If you go to Update Sites and click on the XML file for Joomla! Core then you will see different update XML files depending upon whether the installed version of Joomla is 2.x or 3.x. If you wish to try using a collection type, then this is still possible with a single update XML file, by following the steps below. Firstly delete manually (using phpmyadmin) the records in the database tables update_sites and update_sites_extensions which relate to the helloworld component. Then go into Extensions / Manage / Update and click on Clear Cache. This should have removed all trace of the type="extension" update mechanism. Secondly replace the updateservers section of the manifest file with the following (changing the URL appropriately)
<updateservers> <server type="collection" name="Helloworld Updates">http://localhost/helloworld-updates/list.xml</server> </updateservers>
Zip up the component and install it in the usual way. (Remember, when you install it in this way the version number in the new install file doesn't need to be greater than the version of the one currently installed). Thirdly create a list.xml file which points to the update XML file, and store this in your update server folder. Once again, change the URL and version to match your own situation, making sure that the version quoted in the file is greater than the one currently installed.
<extensionset name="Helloworld Update Collection" description="Helloworld Update as Collection"> <extension name="Helloworld Component" element="com_helloworld" type="component" client="administrator" version="1.0.0" targetplatformversion="3." detailsurl="http://localhost/helloworld-updates/updates.xml"/> </extensionset>
If you test the update process as above you should find it works just the same. However, note that in this case the updates.xml file is not processed during the Find Updates process, so if you have an incompatible minimum value of PHP say, then it won't report it at that stage.