From 8cbce65eb38b2848c93b35627bd0971ca8c6fe97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans-J=C3=BCrgen=20Tappe?= Date: Sun, 7 Nov 2010 13:25:29 +0000 Subject: [PATCH] - Add hint on how to revert changes / reset an eTemplate change as discussed on the developer's list. - Fix typos - Add a reference from the reference.html to the now existing etemplate documentation. --- etemplate/doc/etemplate.html | 589 +++++++++++++++++++++++++++++++++++ etemplate/doc/reference.html | 4 +- 2 files changed, 591 insertions(+), 2 deletions(-) create mode 100644 etemplate/doc/etemplate.html diff --git a/etemplate/doc/etemplate.html b/etemplate/doc/etemplate.html new file mode 100644 index 0000000000..c4d8859098 --- /dev/null +++ b/etemplate/doc/etemplate.html @@ -0,0 +1,589 @@ + + + eGroupWare: eTemplates - Templates and Dialog-Editor + + + + + + +

eTemplate - Templates and Dialog-Editor for eGroupWare

+

by Ralf Becker RalfBecker +AT outdoor-training DOT de

+

Updated by Raphael Alla raphael AT olineopensolutions +DOT com

+

A developers tutorial how to write an application with the new eTemplates.
+It is also an introduction how to write a eGW- 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 pre-acquistion 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 eGW app directory

+

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

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

+2. 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']   = '1.2';
+        $setup_info['et_media']['app_order'] = 100;             // at the end
+        $setup_info['et_media']['tables']    = array('egw_et_media');
+        $setup_info['et_media']['enable']    = 1;
+
+        /* Dependencies for this app to work */
+        $setup_info['et_media']['depends'][] = array(
+                 'appname' => 'phpgwapi',
+                 'versions' => Array('1.2','1.3','1.4')
+        );
+        $setup_info['et_media']['depends'][] = array(
+                 'appname' => 'etemplate',
+                 'versions' => Array('1.2','1.3','1.4')
+        );

+3. Setting up the db-table with the db_tools and setup

+

To enable setup to create a db-table for us and to supply the +so_sql-class with the necessary information, we need to define +the type and size of the fields / columns in our db-table.

+



+

+



We +can use the db-Tools from the etemplate application to create the +file for us: +

+
    +
  1. start the etemplate app and click on the button up, right which says db-Tools
  2. +
  3. select Application: eT-Media
  4. +
  5. type 'egw_et_media' in the field in front of the [Add Table] button and click on the button
  6. +
  7. now use [Add Column] to create the necessary fields as shown on the screenshot
  8. +
  9. Click on [Write Table] (you need to give the webserver write-permission to the setup-dir of et_media + or you will get an error message, leave the write-permission as it is necessary later on too, click on write again)
  10. +
  11. log out and log into setup and start manage applications
  12. +
  13. eT-Media is shown as not installed and only install is offered, check it and submit
  14. +
  15. you can now log out from setup, the db-table is now created

  16. +
  17. In order to be able to use your eT-Media application, do not forget to give yourself access to it + (Admin/User account: check eT-Media)

  18. +
+

4. 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. Save the template in order + to create it
  2. +
  3. an empty template is displayed. An eTemplate can be thought off as a "grid". The first cell may be + a bit tricky to find, but will be highlighted when moving the mouse + over it. On my computer this cell appears in pink as illustrated below:
  4. +

  5. Double + click on the pink spot will bring the following dialog:
  6. +

  7. The + top row allows you to add column and rows to the template. We will need 2 columns and 6 rows
  8. +
  9. Create the following label in the first top left cell:
  10. +
+

+

+
+

+
    +
  1. In the top right cell, we will create a user entry and call it "name": this is the same name as thee column in our + egw_et_media table. This is important as those fields will be populated automatically for us by eGroupWare:
  2. +

  3. +

    Complete the template as follows. The widget used for "type" is a + Selectbox, the one used for "description" is a textarea. Note + that the name of the input is "descr" and not description, as + this is the name of the column in the table. Finally on the last row + we have two widgets of type "Submitbutton" of names "read" + and "save" and of corresponding label.

    +


    +
  4. +
+

Then before moving to the next stage save the template as an XML +file by clicking on "Export XML". Once again the server must have +write permissions on the directory.

+

5. 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');
+        $GLOBALS['egw']->redirect_link('/index.php', 'menuaction=et_media.ui_et_media.edit');
+
+

6. The code for our Application

+

An eGroupWare application is organized around 3 application +layers:

+ +

For this, we create 2 files in the "inc" directory, called +class.bo_et_media.inc.php and class.ui_et_media.inc.php. +In this simple application, the bo layer will be fairly minimal, +this said it is a good idea to create the application using the +right standards from the start.

+

Here is the file /et_media/inc/class.bo_et_media.inc.php: +

+
+<?php
+/**
+ * eGroupWare editable Templates - Example media database (et_media)
+ *
+ * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
+ * @package etemplate
+ * @subpackage et_media
+ * @link http://www.egroupware.org
+ * @author Ralf Becker <RalfBecker@outdoor-training.de>
+ */
+
+include_once(EGW_INCLUDE_ROOT . '/etemplate/inc/class.so_sql.inc.php');
+
+/**
+ * Business object for et_media
+ */
+class bo_et_media extends so_sql
+{
+	/**
+	 * Available media types
+	 *
+	 * @var array
+	 */
+	var $types = array(
+		''      => 'Select one ...',
+		'cd'    => 'Compact Disc',
+		'dvd'   => 'DVD',
+		'book'  => 'Book',
+		'video' => 'Video Tape'
+	);
+	/**
+	 * Constructor initializing so_sql
+	 *
+	 * @return so_et_media
+	 */
+	function bo_et_media()
+	{
+		$this->so_sql('et_media','egw_et_media');		// calling the constructor of the extended bo object
+		$this->empty_on_write = "''";
+	}
+}
+
+

And finally the start of the +/et_media/inc/class.ui_et_media.inc.php:

+
+<?php
+/**
+ * eGroupWare editable Templates - Example media database (et_media)
+ *
+ * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
+ * @package etemplate
+ * @subpackage et_media
+ * @link http://www.egroupware.org
+ * @author Ralf Becker <RalfBecker@outdoor-training.de>
+ */
+
+include_once(EGW_INCLUDE_ROOT . '/et_media/inc/class.bo_et_media.inc.php');
+
+class ui_et_media extends bo_et_media
+{
+	/**
+	 * Public functions callable via menuaction
+	 *
+	 * @var array
+	 */
+	var $public_functions = array(
+		'edit' => True,
+	);
+
+	/**
+	 * Constructor
+	 *
+	 * @return ui_et_media
+	 */
+	function ui_et_media()
+	{
+		$this->bo_et_media();		// calling the constructor of the extended bo object
+
+		$this->tmpl =& CreateObject('etemplate.etemplate','et_media.edit');
+	}
+
+	/**
+	 * Edit a media database entry
+	 *
+	 * @param array $content=null
+	 * @param string $msg=''
+	 */
+	function edit($content=null,$msg = '')
+	{
+		if (is_array($content))		// not first call from index
+		{
+			if ($content['id'] > 0)
+			{
+				$this->read($content);
+			}
+			//echo "<p>edit: content ="; _debug_array($content);
+			$this->data_merge($content);
+			//echo "<p>edit: data ="; _debug_array($this->data);
+
+			if (isset($content['save']))
+			{
+				$msg .= !$this->save() ? lang('Entry saved') : lang('Error: while saving !!!');
+			}
+		}
+
+		// now we fill in the content array for the next call to etemplate.exec
+
+		$content = $this->data + array(
+			'msg' => $msg
+		);
+		$sel_options = array(
+			'type' => $this->types
+		);
+		$this->tmpl->exec('et_media.ui_et_media.edit',$content,$sel_options,$no_button,array(
+			'id' => $this->data['id']
+		));
+	}
+
+

+The edit function is called from our index.php file or as callback +for this form / dialog. In that case $content is an array with the +content the user put into the fields of the dialog.

+

Let first have a look what happened if we called the first time (or +what we do to show the dialog again with the changed data):

+
    +
  1. the $content array is set up with our internal data-array (which is empty on the first call) and the message
  2. +
  3. $sel_options has the options for our selectbox: the options are an array where the keys are the + values returned by the selectbox and the values are what the + selectbox shows to the user. As we can have more than one selectbox + in a dialog, the key in $sel_options need to be the same as the name + of the selectbox.
  4. +
  5. $readonlys: if a field name is set in $readonlys to True, its content is showed readonly + (for regular fields like type Text) or left out for buttons (we use this later to + show the delete-button only when an entry is loaded)
  6. +
  7. the array $preserv is preserved, which means its stored in the app's session-data and is delivered + back like the content of the fields to the callback-function. We use + it here to store the id of the entry. This is similar to use a + hidden input-field in a form, but it does not need to be serialized + by the app and is NOT transmitted to the user and back.
  8. +
  9. at last we call etemplate::exec to show the template with the + content from $content and set the function itself as callback for + the dialog / form.

  10. +
+

Now let's have a look what happens if the user submits the form +and our callback is called: +

+
    +
  1. the callback (this function) is + not the submit-address of the form, the form get's always submitted + to the function process_exec of the etemplate class. This + function changes for some field-types the content (eg. a date-field + consists of 3 single fields, process_exec takes care that it is + delivered back as timestamp, as we set it in content before). It can + even submit the form back to the user if for a address-selection a + search for a pattern has to be performed and the matches are shown + to the user. In this case the callback is NOT called. The same is + true if an int field contains letters or is not within the minimum + or maximum set. Not all of the is already working, it will + follow in the next days/weeks.
    For the specialist + process_exec uses $_POST and ignores $_GET set as query in the url.
  2. +
  3. the so_sql function data_merge, copies all values from $content, which are columns in the db-table, + in our internal data array. Values which are not real data, like + buttons pressed are not copied (!).
  4. +
  5. if $content['save'] is set, the [Save] button has been pressed ('save' is the name NOT the label of + the save button), in that case we use so_sql's save function to save + the content of our internal data-array to the db.
  6. +
  7. the same check is used for the [Read]: we uses the content of all fields to search db for matching + entries. The user can use wildcards to perform a search on all + field. The wildcards are '*' and '?', so_sql translates them into sql-wildcards.
  8. +
  9. if the search return False we just set our message var.
  10. +
  11. if something is found we use so_sql's init-function to set the data of the first match. Later on + we will show a list if more than one entry is found.
  12. +
  13. after that the content array is filled again as described above.

  14. +
+

Now we are able to store entries in the db and retrieve them by +searching the database for patterns in the different fields. You can +try your new application now. You can create new records and save +them. By just entering the name or author, the database will find the +corresponding match and populate the form for you.

+


We are only lacking some way to show if we get more than one +match on a search, that's what we are going to implement next:

+

7. Adding a list-dialog for the search-function

+

First we need to create an other eTemplate to show the list: +'et_media.show' as follows. This is made of a label of name +"msg" (to display messages), an HorizontalRule widget, and a +Template widget: we will use a "sub template" called +et_media.show.rows to display the rows of the search function. I have +set the option of the template widget to "entry" as this is the +name we will use to access to the data in the sub-template. +

+




+

+

The 'et_media.show.rows' template is +created as a 3x2 table. On the header row, two labels "Name" and +"Author" and one empty cell.

+

ond row, two labels of name ${row}[name] and ${row}[author]. In the last cell a +submitButton of label "Edit" and of name "edit[$row_cont[id]]" +

+




+

+

The class of the header row is "th" and the class of the +content row is "row". eTemplate will automatically vary the +colors of the "row" class to provide a nice visual effect.

+

Here is a view of the et_media.show template once the two +templates have been created:

+




+

+

We need some code / a function in the class to call the template +and fill the content:

+
+	/**
+	 * Showing entries from the media database
+	 *
+	 * @param array $found
+	 */
+	function show($found=null)
+	{
+		if (!is_array($found) || !count($found))
+		{
+			$this->edit();
+			return;
+		}
+		array_unshift($found,false);	// change the array to start with index 1
+		$content = array(
+			'msg' => lang('%1 matches on search criteria',count($found)-1),
+			'entry' => $found,
+		);
+		$this->tmpl->read('et_media.show');
+
+		$this->tmpl->exec('et_media.ui_et_media.edit',$content);
+	}
+}
+

+This function is called by edit with the matches of a search:

+
    +
  1. We build an array with all the matches, the index in that array is the row-number starting with 1(!) + ($entry = array('empty') + $found; would do the same).
    + The names in the data-row (last row) of 'et_media.show.rows' are like + '${row}[name]'. Variable expansion is performed on each name and + expands that for the first row to '1[name]' which addresses the name + in the first match.
  2. +
  3. $content contains again 'msg' which we set to the number of entries found and the above array with + the data of all rows under the key 'entry', as we put that in + Options for the field loading the sub-template 'et_media.show.rows'. + It not necessary to put something in Options-field / use a sub-array + for a sub-template, but it can be very helpful to organize a complex + content-array. (As an exercise you can remove 'entry' from the + Options-field and change the function accordingly).
  4. +
  5. we now explicitly read the template 'et_media.show' (the constructor reed 'et_media.edit') and + execute it again with the edit function as callback (because of + that, show does NOT need to be listed in public_functions)
  6. +
  7. as 'et_media.show.rows' contains only one data-row, but field names with variables to expand, that row is auto-repeated for as + many data we put into the content array (or the sub-array if we used the Options-field).
  8. +
+

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

+
+			elseif (isset($content['read']))
+			{
+				unset($content['id']);					// not set by user, so don't use for search
+				unset($content['read']);
+				$found = $this->search($content,False,'name,author');	// searches by using the no-empty fields
+
+				if (!$found)
+				{
+					$msg .= lang('Nothing matched search criteria !!!');
+				}
+				elseif (count($found) == 1)
+				{
+					$this->init($found[0]);				// only one match --> show it in the editor
+				}
+				else
+				{
+					$this->show($found);				// multiple matches --> use the show function/template
+					return;
+				}
+			}
+			elseif (isset($content['entry']['edit']))			// the callback from for the show function/template
+			{								// the id is set via the button name of '$row_cont[id]'
+				list($id) = each($content['entry']['edit']);		// note its not only ['edit'] !!!
+				if ($id > 0)
+				{
+					$this->read(array('id' => $id));
+				}
+			}
+
+
    +
  1. the first part should be self-explaining, we call show with $found if it contain more than + one entry.
  2. +
  3. The show function uses edit as callback, the [Edit] buttons + in each row has 'edit[$row_cont[id]]' as name. If an [Edit] button + is pressed $content['entry']['edit'] is set to the id of the entry + of that row. We use that id to read the whole entry.
  4. +
+

This is what the new "show" template looks like:

+




+

+

While making these changes we can add a [Cancel] and [Delete] +button too:

+
+			elseif (isset($content['cancel']))
+			{
+				$content = array(); 										// clear the contents
+			}
+			elseif (isset($content['delete']))
+			{
+				$this->bo->so->delete($r_id);
+				$content = array(); 										// clear the content
+			}
+			
+            $no_button = array(     										// no delete button if id == 0 --> entry not saved
+                    'delete' => !$this->content['id']; 
+            );
+
+
    +
  1. on cancel we just clear the internal data-array with so_sql's init function.
  2. +
  3. on delete we have to call so_sql's delete before (it deletes the db-row corresponding + with our internal data-array)
  4. +
  5. the last block checks if the id field is set (it can only be + set by a read or save) and disables the [Delete] button if not + ($this->db_key_cols[$this->autoinc_id] == 'id').

  6. +
+

Of course we have to add this buttons to the template +'et_media.edit'. I trust you can add 2 submit buttons with the names +'cancel' and 'delete', a Label and a nice help messages by now without +looking at a screenshot ;-).

+

The eTemplate is saved in the eGroupware database. If changes done to the +eTemplate should be reverted, a eTemplate setup file is +required, see section Dumping the eTemplate to a File for Distribution. +Note that reverting only works if +a valid version has previously been dumped to a distribution file or if a new +revision identifier of the template has been used to save the changes.

+

8. 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 possibilities to create it automatically:

+
    +
  1. Use the [Write Langfile] button in the eTemplate editor (put the app-name 'et_media' in the name-field + first)
    That will NOT write the messages in the classes!!!
  2. +
  3. We can use the TranslationTools to scans our sources for lang('...') calls ([search new phrases] button).
  4. +
  5. Other phrases like the media types can be added manually via [Add] button in the Translation Tools.
  6. +
+

9. Dumping the eTemplate to a File for Distribution

+

To be able to put the eTemplates in CVS and to ship them with your +app, you need to dump them in a file first. +

+

This is done in the eTemplate editor by putting the app-name or an +template-name in the Name field and clicking on the button +[Dump4Setup]. This creates the file +et_media/setup/etemplates.inc.php. The eTemplate-class loads +this file whenever it finds a new version automatically.

+

To recover a changed eTemplate to the state saved in the distribution file, the following +steps need to be performed:

+ +

In case the modification was done in a sub-template, e.g. the +definition of the rows in a list view, the correct (sub-) template name and +version needs to be chosen for deletion. It is visible in the edit window of the +elements modified.

+

10. Further information

+

Please note: All files of the et_media example can be found in the et_media sub-directory of +etemplate's doc directory. Symlinking or coping to the eGroupWare install directory, allows to +immediately install it via setup.

+
    +
  1. the reference-documentation of the eTemplates
  2. +
  3. for all functions and parameters of the etemplate-class(es) look in the + phpDocumentor docu of etemplate + created from comments (yes there are comments) in the sources: + +
  4. +
  5. for all functions and parameters of the so_sql-class look in the comments of the file + class.so_sql.inc.php
  6. +
  7. for setup, the necessary files of an app or the format of + tables_current.inc.php look at the excellent docu + of setup3 in the doc-dir of the setup app.

  8. +
+

That's it - please write to our developers +list or developer forum, +if you have further questions or comments about the tutorial or eTemplate.

+ diff --git a/etemplate/doc/reference.html b/etemplate/doc/reference.html index 4800a1fd98..1c777b1497 100644 --- a/etemplate/doc/reference.html +++ b/etemplate/doc/reference.html @@ -1052,8 +1052,8 @@ This is done in most cases by the underlaying html-class and not direct in eTemp eTemplates to define the UI of the new widget and are stored in the eTemplate's inc-dir or the inc-dir of a eGroupWare application. The editor and the etemplate-class autoload the existing extensions.

-I will made more documentation about the interface availible soon. For now have a look for the source -of the existing extensions. +I have made more documentation about the interface available. For +additional information, have a look for the source of the existing extensions.

please contact me if you have further questions or comments about the eTemplates