eTemplate - Templates and Dialog-Editor for phpGroupware

RalfBecker@outdoor-training.de

A developers tutorial how to write an application with the new eTemplates.
It is also an introduction how to write a phpgw- and setup(3)-compatible app.


Introduction - The concept of the eTemplates

The eTemplates

Tutorial / Example: a simple media database

As an example we will run now through the necessary steps to create a simple media database using eTemplates and other tools and classes from the eTemplate app: db-tools and class.so_sql.inc.php.

Out media database should have the usual fields: name, author, description, type: BOOK, CD, VIDEO and should be able to edit records and search for them.

As a preaquistion you need to get / checkout the etemplate app, install the app via setup/manage applications and enable your account for using the app (Admin/User account: check eTemplates).

1. Creating a new phpgw app directory

Each app need a name, eg. 'et_media'. We now need to create the following directory structur above the phpgroupware dir:

et_media				(that has to be identical to our app-name)
	+ setup				(files necessary for the setup Programm, give the webserver write-permission to that dir)
	+ inc				(class-files)
	+ templates			(templates, still need to store the images and get around a lot of complains from the api)
		+ default
			+ images	(here goes our images / icons)

2. registering the app manualy

To be able to see the app in the navbar and call it we need to do the following steps (later this can be done via setup)

  1. login to phpgw as an admin
  2. call the admin app (the first icon with the tower)
  3. start Admin/Applications
  4. click on Add
  5. type in 'et_media' for the app-name and eg. 'eT-Media' for the titel, leave the rest alone and hit Add
  6. start Admin/User accounts and enable the new app for your account

3. creating et_media/setup/setup.inc.php

That files contains the necessary information for setup to install the app.

<?php
	$setup_info['et_media']['name']      = 'et_media';
	$setup_info['et_media']['title']     = 'eT-Media';
	$setup_info['et_media']['version']   = '0.9.15.001';
	$setup_info['et_media']['app_order'] = 100;	// at the end
	$setup_info['et_media']['tables']    = array('phpgw_et_media');
	$setup_info['et_media']['enable']    = 1;

	/* Dependacies for this app to work */
	$setup_info['et_media']['depends'][] = array(
		 'appname' => 'phpgwapi',
		 'versions' => Array('0.9.13','0.9.14','0.9.15')
	);
	$setup_info['et_media']['depends'][] = array(	// this is only necessary as long the etemplate-class is not in the api
		 'appname' => 'etemplate',
		 'versions' => Array('0.9.13','0.9.14','0.9.15')
	);

4. setting up the db-table with the db_tools and setup

To enable setup to create a db-table for us, we need to define the fields we want.
We can use the db-Tools from the etemplate app to create the file for us:

  1. start the etemplate app and click on the button up, right which says db-Tools
  2. select Application: eT-Media
  3. type: phpgw_et_media in the field in front of the [Add Table] button and click on the button
  4. now use [Add Column] to create the necessary fields as shown on the screenshot
  5. Click on [Write Table] (If you get the error-message like in the screenshot, you need to give the webserver write-permission to the setup-dir of et_media, leave the write-permission as it is necessary later on too, click on write again)
  6. log out and log into setup again and start manage applications
  7. eT-Media is shown now as installed but need upgrade, don't select upgrade, check remove and submit
  8. the next page should tell you everythings allright so click on go back (or if u use konqueror reload)
  9. now for eT-Media only install is offerd, check it and submit
  10. you can now log out of setup, out db-table is now created

5. creating an eTemplates for the edit-dialog

Now we need a nice edit dialog and use the eTemplate editor to set it up:

  1. start the etemplate app and type 'et_media.edit' in the name field
  2. enter the field-types and other data as shown above
  3. click on the [+] in the first column of the last row to add more rows
  4. click on save to save the dialog / template
  5. you can use [Show (no save)] to have a look at it:

As you see above i added an application titel, a horizontal rule after it and some space (empty label's). Do so if you want.

6. setting up the index page

The index page is only used if someone clicks on the navbar icon (or on the black cross as we haven't supplied one so far).
Create the file /et_media/index.php with the following content:

<?php
	$GLOBALS['phpgw_info']['flags'] = array(
		'currentapp'	=> 'et_media',
		'noheader'	=> True,
		'nonavbar'	=> True
	);
	include('../header.inc.php');

	$et_media = CreateObject('et_media.et_media');

	$et_media->edit();

	$GLOBALS['phpgw']->common->phpgw_footer();

7. the code of class.et_media.inc.php

As a first step, we only save new entries. The code of the app is in /et_media/inc/class.et_media.inc.php:

<?php
	/**************************************************************************\
	* phpGroupWare - eTemplates - Tutoria Example - a simple MediaDB           *
	* http://www.phpgroupware.org                                              *
	* Written by Ralf Becker                   *
	* --------------------------------------------                             *
	*  This program is free software; you can redistribute it and/or modify it *
	*  under the terms of the GNU General Public License as published by the   *
	*  Free Software Foundation; either version 2 of the License, or (at your  *
	*  option) any later version.                                              *
	\**************************************************************************/

	/* $Id$ */

	if(!isset($GLOBALS['phpgw_info']['flags']['included_classes']['so_sql']))
	{
		include(PHPGW_API_INC . '/../../etemplate/inc/class.so_sql.inc.php');
		$GLOBALS['phpgw_info']['flags']['included_classes']['so_sql'] = True;
	}

	class et_media extends so_sql
	{
		var $messages = array(
			'nothing_found' => 'Nothing matched search criteria !!!',
			'anz_found' => '%d matches on search criteria',
			'saved' => 'Entry saved',
			'error_writeing' => 'Error: writeing !!!'
		);
		var $types = array(
			'' => 'Select one ...',
			'cd' => 'Compact Disc',
			'dvd' => 'DVD',
			'book' => 'Book',
			'video' => 'Video Tape'
		);

		function et_media($lang_on_messages = True)
		{
			$this->tmpl = CreateObject('etemplate.etemplate','et_media.edit');

			$this->so_sql('et_media','phpgw_et_media');	// sets up our storage layer using the table 'phpgw_et_media'
			$this->empty_on_write = "''";	// that means if a column is empty how to write in the db, the default is NULL

			$this->public_functions += array(
				'edit' => True,
				'writeLangFile' => True
			);

			if ($lang_on_messages)
			{
				reset($this->messages);
				while (list($key,$msg) = each($this->messages))
					$this->messages[$key] = lang($msg);
			}
		}

		function edit($content='',$msg = '')
		{
			if (is_array($content))	// not first call from index
			{
				if ($content['id'] > 0)
				{
					$this->read($content);
				}
				$this->data_merge($content);

				if (isset($content['save']))
				{
					$msg .= $this->messages[!$this->save() ? 'saved' : 'error_writeing'];
				}
				elseif (isset($content['read']))
				{
					unset($content['id']);
					$found = $this->search($content,False,'name,author');

					if (!$found)
					{
						$msg .= $this->messages['nothing_found'];
					}
					else
					{
						$this->init($found[0]);
					}
				}
			}

			// now we filling the content array for the next call to etemplate.exec

			$content = $this->data + array(
				'msg' => $msg
			);
			$sel_options = array(
				'type' => $this->types
			);
			$no_button = array(
				'delete' => !$this->data[$this->db_key_cols[$this->autoinc_id]]
			);
			$this->tmpl->exec('et_media.et_media.edit',$content,$sel_options,$no_button,array(
				'id' => $this->data['id']
			));
		}
	}

8. adding the search-function and a list-dialog

As saveing and reading of entries is working now we want to search for an entry and show a list of the result (if it's more than one).
First we need to create an other eTemplate to show the list: 'et_media.show'

As you see the templates includes an other template: 'et_media.show.rows'

We need some code in the class to call the template and fill the content:

	function show($found)
	{
		if (!is_array($found) || !count($found))
		{
			$this->edit();
			return;
		}
		reset($found);
		for ($row=1; list($key,$data) = each($found); ++$row)
		{
			$entry[$row] = $data;
		}
		$content = array(
			'msg' => sprintf($this->messages['anz_found'],count($found)),
			'entry' => $entry
		);
		$this->tmpl->read('et_media.show');

		$this->tmpl->exec('et_media.et_media.edit',$content);
	}

To call the show function, we need to make some changes to the edit-function too:

				elseif (isset($content['read']))
				{
					unset($content['id']);
					$found = $this->search($content,False,'name,author');

					if (!$found)
					{
						$msg .= $this->messages['nothing_found'];
					}
					elseif (count($found) == 1)
					{
						$this->init($found[0]);
					}
					else
					{
						$this->show($found);
						return;
					}
				}
				elseif (isset($content['entry']['edit']))
				{
					list($id) = each($content['entry']['edit']);
					if ($id > 0)
					{
						$this->read(array('id' => $id));
					}
				}

While makeing this changes we can add a [Cancel] and [Delete] button too:

				elseif (isset($content['cancel']))
				{
					$this->init();
				}
				elseif (isset($content['delete']))
				{
					$this->delete();
					$this->init();
				}

Of course we have to add this buttons to the template 'et_media.edit'

9. creating the english lang-file

To get rid of the stars '*' behind each Label and to be able to translate the app in other languages we need to create a lang-file
There are 2 possibilties to create it automaticaly:

  • Use the [Write Langfile] button in the eTemplate editor (put the app-name 'et_media' in the name-field first)
    That will omitt our own messages in the class!!!
  • We use a function in our class to call etemplate::writeLangFile('et_media','en',$extra) and can so supply some extra strings.
    If we add this function to the public_functions-array in our class, we can just call this function via the browser:
    http://ourDomain/phpgroupware/index.php?menuaction=et_media.et_media.writeLangFile (the errormsg can be savely ignored)
    This is the function (don't forget to add it like the edit-function to public_functions):

    	function writeLangFile()
    	{
    		$etm = new et_media(False);	// no lang on messages
    
    		$this->tmpl->writeLangFile('et_media','en',$etm->messages);
    	}