Path

ez.no / ezpublish / documentation / development / extensions / building an ez publish module


Building an eZ publish module

These documentation pages are no longer maintained. Please visit the new documentation site.

The purpose of this rather short tutorial is to show users of eZ publish 3 willing to write some additional functions by exploiting the extensions functionality.

In the following article where ever we will mention an absolute path it will mean the path from the eZ publish root. We also suppose, that URL for our eZ publish site is http://www.example.com/path/index.php/mysite/

We will develop a simple extension for accessing EUR exchange rates. Of course, we need some source of exchange rates in an usable format. In our tutorial, we will use a service provided by European Central Bank. You can have a look at http://www.ecb.int/stats/eurofxref/eurofxref-xml.html to see actual exchange rates as HTML page. (This information is updated every working day at 2.15pm CE(S)T.) We are lucky because the bank provides this information also in the XML format at http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml

Let's have a brief look at this file:

<?xml version="1.0" encoding="UTF-8"?>

<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01"

xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">

<gesmes:subject>Reference rates</gesmes:subject>

<gesmes:Sender>

<gesmes:name>European Central Bank</gesmes:name>

</gesmes:Sender>

<Cube>

<Cube time='2004-04-15'>

<Cube currency='USD' rate='1.1912'/>

<Cube currency='JPY' rate='129.39'/>

<Cube currency='DKK' rate='7.4443'/>

...

<Cube currency='ZAR' rate='7.8591'/>

</Cube>

</Cube>

</gesmes:Envelope>

Perfect! We see that the most important information is stored in attributes of Cube tags: if the tag has the attribute named time, its value is the date, if it has the attribute named currency, its value is the currency symbol and the value of the attribute rate is the actual exchange rate. The format of the rate is suitable for us, so we do not need to do any post-processing.

In this tutorial we develop an extension named eurofxref which will contain one module with the same name. We want to have the possibility of including exchange rates to our templates and also we prepare an overview page like http://www.example.com/path/index.php/mysite/eurofxref/overview to see the entire table of exchange rates.

First, create the directory eurofxref under the /extension directory located in the root directory of eZ publish. If the /extension directory does not exist, then you have to create it. You must tell eZ publish that this extension exists by adding ActiveExtensions[]=eurofxref in the [ExtensionSettings] section of site.ini files. Preferably, you should do this by adding the following lines in /settings/override/site.ini.append.php. Please note that if you already have either [ExtensionSettings] or [RoleSettings] section in your site ini file, you have to add the line(s) to the corresponding section(s).

site.ini.append.php (partial content):

 

[ExtensionSettings]

ActiveExtensions[]=eurofxref

 

[RoleSettings]

PolicyOmitList[]=eurofxref

The last line ensures that an anonymous user will be not prompted for a login name and a password, when accessing information through the eurofxref module, for example by browsing http://www.example.com/path/index.php/mysite/eurofxref/overview. The eurofxref in the URL represents the module name, not the extension name. Every module can have an unlimited number of "views" - they represent different views of the data in the module. You can choose which view you want to see by entering its name after the name of the module (and the slash) in a URL.

Now create the directories design, modules and settings under /extension/eurofxref. Under design create the path /extension/eurofxref/design/standard/templates/eurofxref (by creating one subdirectory in this path at a time). In this directory we will put our template files, hence the directory name design. standard stands for the default design, templates is, as the name says, the directory used for storing templates and eurofxref is our "identifier". From now on, we can use an eZ publish URI like design:eurofxref/name_of_template.tpl for accessing templates stored in this directory.

Directory structure
Under /extension/eurofxref/settings create the following two files:

design.ini.append.php (Exact content)

 

[ExtensionSettings]

DesignExtensions[]=eurofxref

and

module.ini.append.php (Exact content)

 

[ModuleSettings]

ExtensionRepositories[]=eurofxref

As you have probably found out, the purpose of design.ini.append.php is to allow using of templates located in our extension, in module.ini.append.php we say to eZ publish we are having modules in this extension.

Now we are coming to the most important part: creating the module eurofxref itself. Under /extension/eurofxref/modules create a directory eurofxref (the name of the module) and create the following files:

module.php (Exact content)

 

<?php

 

$Module = array( 'name' => 'Eurofxref' );

 

$ViewList = array();

$ViewList['overview'] = array(

   'script' => 'overview.php',

   'params' => array ( ) );

 

?>
overview.php (Exact content)

 

<?php

 

include_once( 'kernel/common/template.php' );

 

$tpl =& templateInit();

 

$Result = array();

$Result['content'] =& $tpl->fetch( 'design:eurofxref/overview.tpl' );

$Result['path'] = array( array( 'url' => false,

                               'text' => 'Euro Exchange Rates' ) );

?>

and

function_definition.php (Exact content)

 

<?php

 

$FunctionList = array();

 

$FunctionList['fxref'] = array(

'name' => 'fxref',

'call_method' => array( 

'include_file' => 'extension/eurofxref/modules/eurofxref/classes/eurofxref.php',

'class' => 'EuroFxRef',

'method' => 'fetchFX' ),

'parameter_type' => 'standard',

'parameters' => array() );

 

?>

The module.php file is used to connect the different views in the module, represented by keys in the $ViewList array (in our case 'overview') with the file names (overview.php). We can see that overview.php contains simple code to fetch and process the template file design:eurofxref/overview.tpl. We will create this file later.

If you have {let var_name=fetch( 'module', 'function', 'parameters' )} in the template, eZ publish will call a method whose parameters are defined in the file function_definition.php under the corresponding module. Having a look in our function_definition.php file, we see that if the template fetches the function fxref in our module (eurofxref), eZ publish will call the method EuroFxRef::fetchFX() which will be defined in /extension/eurofxref/modules/eurofxref/classes/eurofxref.php. In our simple example, we do not have any parameters in the fetch.

Create the directory classes under /extension/eurofxref/modules/eurofxref and place the following file in it:

eurofxref.php (Exact content)

 

<?php

 

include_once( 'lib/ezxml/classes/ezxml.php' );

 

class EuroFxRef

{

   // static

   function fetchFX()

   {

       $result = array( 'date' => false, 'fx' => array() );

 

       $fxXML = file_get_contents("http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml");

 

       $xml = new eZXML();

       $dom =& $xml->domTree( $fxXML );

       $fxArray =& $dom->elementsByName( 'Cube' );

       foreach ( $fxArray as $fxRate )

       {

           if ( !$fxRate->hasAttributes() )

               continue;

           $currency = $fxRate->attributeValue( 'currency' );

           if ( $currency === false )

           {

               if ( $fxRate->attributeValue( 'time' ) != false )

               {

                   $datePieces = explode( '-', $fxRate->attributeValue( 'time' ) );

                   $result['date'] = mktime( 0, 0, 0, $datePieces[1], $datePieces[2], $datePieces[0] );

               }

           }

           else

           {

               $value = $fxRate->attributeValue( 'rate' );

               $result['fx'][$currency] = $value;

           }

       }

       return array( 'result' => $result );

   }

}

 

?>

Note that we are returning our data ($result) in an array element with the key 'result'.

When the file is parsed and the result is returned, the $result array looks like:

$result = array( 'date' => 1081980000,

                    'fx' => array( 'USD' => 1.1912,

                                   'JPY' => 129.39,

                                   'DKK' => 7.4443,

                                   ...

                                   'ZAR' => 7.8591 ) )

The last file which we need to create before testing our new extension, is the template file overview.tpl under /extension/eurofxref/design/standard/templates/eurofxref. Put the following contents in it:

overview.tpl (Exact content)

 

<h1>Euro foreign exchange reference rates</h1>

 

{let rates=fetch( 'eurofxref', 'fxref' )}

Date: {$rates.date|l10n( 'date' )}<br />

<br />

 

<table border="1">

<tr><th> Currency </th><th> Value </th></tr>

{section loop=$rates.fx}

<tr><td> {$:key} </td><td> {$:item|l10n( 'number' )} </td></tr>

{/section}

</table>

{/let}

<br />

 

Source: <a href="http://www.ecb.int">European Central Bank</a>

As outlined before, we use let rates=fetch( 'eurofxref', 'fxref' ) to fetch data through the function EuroFxRef::fetchFX(). Using $rates.date we can output the date and we can cycle through elements of $rates.fx (with loop=$rates.fx).

If you point your browser to http://www.example.com/path/index.php/mysite/eurofxref/overview you should see a table with currency symbols and rates:

Screenshot of module output

You can print the current exchange rate of your currency in any template just by including the following code in it.

(partial content)

 

{let rates=fetch( 'eurofxref', 'fxref' )}

1 EUR = {$rates.fx.USD|l10n( 'number' )} USD

{/let}

If you want to use this code on pages which are frequently used then you may consider some optimization. The problem is that the code will download the XML document every time the fetch function is called. One possible solution is to store the values into a database and if we know the data is valid next fetches will use these stored values instead of downloading the XML document from web again and again.

The second solution is much simpler but not so sophisticated. We can use the template function cache-block to cache a generated part of the page. Using this function is very simple:

(partial content)

 

{cache-block expiry=3600}

{let rates=fetch( 'eurofxref', 'fxref' )}

1 EUR = {$rates.fx.USD|l10n( 'number' )} USD

{/let}

{/cache-block}

We set the expiration period by setting the expiry parameter to the maximum number of seconds the element might be in the cache. In our example we use one hour (3600 seconds). We should put the entire content of overview.tpl into a cache block as well. Please note that this will cache something like "1 EUR = 1.1912 USD" rather than the information about rates. If you will use the code elsewhere it will download the XML document again.

If you want to create views that have parameters in an URL, (e.g. http://www.example.com/path/index.php/mysite/eurofxref/history/EUR, where history is the name of a view and EUR is a parameter), you have to add additional code to module.php, for example:

module.php (partial content)

 

$ViewList['history'] = array(

   'script' => 'history.php',

   'params' => array ( 'CurrencySymbol' ) );

You can retrieve the value of the parameters in your script with:

history.php (partial content)

 

<?php

   $currencySymbol = $Params['CurrencySymbol'];

A more complicated addition to our example is adding parameters to the fetch function called from a template. However this exceeds the scope of this article, we recommend to read the documentation and browse the eZ publish source code, for example have a look at /kernel/content/function_definition.php and see the source code of any function defined with the call_method key.

You can download the whole source code of the extension from this tutorial from http://ez.no/community/contributions/examples/euro_exchange_rates.

Comments

Fatal error: Call to a member function on a non-object

I'm using eZ Publish 3.9.2.
I download the source code of the Euro Exchange Rates smaple and upload it to my site.
When I pointed my browser to



http://www.mydomain.com/index.php?/chi/eurofxref/overview



the following error message displays:



Fatal error: Call to a member function on a non-object in /home/mydomain/extension/eurofxref/modules/eurofxref/classes/eurofxref.php on line 16


Fatal error: eZ publish did not finish its request


 

The execution of eZ publish was abruptly ended, the debug output is present below.




The line 16 of eurofxref.php is:



$fxArray =& $dom->elementsByName( 'Cube' );



Thanks!

OnlyBlue

How to call non-static method of class

Hello,

Could explain, if it is possible to call non-static methods of a class, like
euroFxRef->fetchFX(), not EuroFxRef::fetchFX()

If yes, then how to initialize such an object, where to call a constructor, few lines of the code would be very nice,

TIA,

Mihhail

Plz help me Module not found

Hi to all
I created the extension eurofxref under the steps in tutorial but when I write the url to the module, the browser shown "Module not found" .
In other way, I downloaded the eurofxref from site because (maybe I do some error) and after download it, I put it in the extension folder and I write the code in /settings/override/site.ini.append.php
[ExtensionSettings]
ActiveExtensions[]=eurofxref
[RoleSettings]
PolicyOmitList[]=eurofxref
when I log to the site by URL : http://localhost/index.php/cvc/eurofxref/overview/
the browser give me Module not found.
Note: My site name is cvc.

Modules not showing

I had the same problem. Did the tutorial (to the letter), module popped up in admin, but client-side got 'Module not found.'

I solved it by setting the correct permissions for the files. (ok, not the correct ones, but it worked.)

Try this (if eZ Publish is running on a UNIX or LINUXlike platform):
/ez/publish/root # chmod -R 777 *

Admitted, this might be overkill, but it works! (for me...)

help me please

I have created an extension (exemple : eurofxref), the extension is recognized but not the module eurofxref (idem for then exemple Hello).
Version used : 3.4.1
Thank you
hdisdier@prodidact.net

Contents

Development

Extensions
    Translation
    Introduction to extensions
    Building an eZ publish module
    Design extension
    Datatypes
    Workflow events
    Module
    Template operator
    Template function
eZ publish datamodel
eZ publish tuning and stability
Importing attribute data
Kernel
Libraries
Scripting
Standards
System overview
Test Suite
Using Doxygen to create API documenta...


Created

26/04/2004
2:36:57 pm
by Jan Kudlicka

Last updated

08/04/2005
11:03:34 am
by Ole Morten Halvorsen

Authors

Jan Kudlicka
Ole Morten Halvorsen



This page is part of the eZ Publish documentation. The documentation is available under the GNU Free Documentation License. All contributions will be released under the terms of this license.