remove phpgwapi and etemplate added to get it for history of api

This commit is contained in:
Ralf Becker 2016-05-12 14:35:59 +02:00
parent eea3aac80d
commit 4a167f0bbf
1123 changed files with 0 additions and 80788 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

View File

@ -1,42 +0,0 @@
<?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>
* @version $Id$
*/
include_once(EGW_INCLUDE_ROOT . '/etemplate/inc/class.so_sql.inc.php');
/**
* Business object for et_media
*/
class bo_et_media extends so_sql
{
/**
* Availible media types
*
* @var array
*/
var $types = array(
'' => 'Select one ...',
'cd' => 'Compact Disc',
'dvd' => 'DVD',
'book' => 'Book',
'video' => 'Video Tape'
);
/**
* Constructor initialising so_sql
*
* @return so_et_media
*/
function bo_et_media()
{
$this->so_sql('et_media','egw_et_media');
$this->empty_on_write = "''";
}
}

View File

@ -1,137 +0,0 @@
<?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>
* @version $Id$
*/
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,
'writeLangFile' => 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 !!!');
}
elseif (isset($content['read']))
{
unset($content['id']);
unset($content['read']);
$found = $this->search($content,False,'name,author');
if (!$found)
{
$msg .= lang('Nothing matched search criteria !!!');
}
elseif (count($found) == 1)
{
$this->init($found[0]);
}
else
{
$this->show($found);
return;
}
}
elseif (isset($content['cancel']))
{
$this->init();
}
elseif (isset($content['delete']))
{
$this->delete();
$this->init();
}
elseif (isset($content['entry']['edit']))
{
list($id) = each($content['entry']['edit']);
if ($id > 0)
{
$this->read(array('id' => $id));
}
}
}
// 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.ui_et_media.edit',$content,$sel_options,$no_button,array(
'id' => $this->data['id']
));
}
/**
* 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)),
'entry' => $found,
);
$this->tmpl->read('et_media.show');
$this->tmpl->exec('et_media.ui_et_media.edit',$content);
}
}

View File

@ -1,22 +0,0 @@
<?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>
* @version $Id$
*/
$GLOBALS['egw_info'] = array(
'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');

View File

@ -1,14 +0,0 @@
to install et_media the example app from the eTemplate Tutorial you need to do the followin steps:
1) in a shell (on windows just copy the et_media dir into your egw-install dir)
cd /www/egroupware # or whatever you egw-install-dir is
mv etemplate/doc/et_media .
ln -s et_media etemplate/doc
2) install et_media via setup
3) enable it for you as a user
Questions?
please ask RalfBecker@outdoor-training.de

View File

@ -1,23 +0,0 @@
%d matches on search criteria et_media de %d Ergebnisse bei der Suche
author et_media de Author
book et_media de Buch
clears the form, without changing anything et_media de Löscht das Formular ohne etwas zu ändern
click here to edit the entry et_media de hier clicken um den Eintrag zu ändern
compact disc et_media de Compact Disk
deletes an entry et_media de löscht einen Eintrag
description et_media de Beschreibung
dvd et_media de DVD
entry saved et_media de Eintrag gesichert
error: writeing !!! et_media de Fehler: beim schreiben !!!
et_media common de eTemplates MedienDB
etemplates mediadb et_media de eTemplates MedienDB
here goes the name of the publication / record et_media de hierhin kommt der name der Publikation
nothing matched search criteria !!! et_media de Keine Einträge zu diesen Suchbegriffen !!!
please use name, first name et_media de bitte benutzen sie Name, Vorname
reads or searches for entries matching the criteria above et_media de Liest oder Sucht nach Einträgen die den obigen Kriterien entsprechen
saves the change to the db et_media de sichert die Änderungen in der Datenbank
select one ... et_media de Eine auswählen ...
select the type fitting most et_media de den zutreffensten Typ auswählen
type et_media de Typ
video tape et_media de Videoband
we have a fulltext search using that description et_media de wir haben eine Volltextsuche die diese Beschreibung nutzt

View File

@ -1,29 +0,0 @@
%d matches on search criteria et_media en %d matches on search criteria
author et_media en Author
book et_media en Book
cancel et_media en Cancel
clears the form, without changing anything et_media en clears the form, without changing anything
click here to edit the entry et_media en click here to edit the entry
compact disc et_media en Compact Disc
delete et_media en Delete
deletes an entry et_media en deletes an entry
description et_media en Description
dvd et_media en DVD
edit et_media en Edit
entry saved et_media en Entry saved
error: writeing !!! et_media en Error: writeing !!!
et_media common en eTemplates MediaDB
etemplates mediadb et_media en eTemplates MediaDB
here goes the name of the publication / record et_media en here goes the name of the publication / record
name et_media en Name
nothing matched search criteria !!! et_media en Nothing matched search criteria !!!
please use name, first name et_media en please use Name, First Name
read et_media en Read
reads or searches for entries matching the criteria above et_media en reads or searches for entries matching the criteria above
save et_media en Save
saves the change to the db et_media en saves the change to the db
select one ... et_media en Select one ...
select the type fitting most et_media en select the type fitting most
type et_media en Type
video tape et_media en Video Tape
we have a fulltext search using that description et_media en we have a fulltext search using that description

View File

@ -1,29 +0,0 @@
%d matches on search criteria et_media en %d coincidencias en el criterio de búsqueda
author et_media en Autor
book et_media en Libro
cancel et_media en Cancelar
clears the form, without changing anything et_media en limpia el formulario, sin cambiar nada
click here to edit the entry et_media en pulse aquí para editar la entrada
compact disc et_media en Compact Disc
delete et_media en Borrar
deletes an entry et_media en borra una entrada
description et_media en Descripción
dvd et_media en DVD
edit et_media en Editar
entry saved et_media en Se ha guardado la entrada
error: writeing !!! et_media en ¡¡Error al escribir!!!
et_media common en Base de datos de medios de eTemplate
etemplates mediadb et_media en Base de datos de medios de eTemplate
here goes the name of the publication / record et_media en Aquí va el nombre de la publicación o disco
name et_media en Nombre
nothing matched search criteria !!! et_media en ¡¡No se han encontrado resultado para el criterio de búsqueda!!!
please use name, first name et_media en por favor, use Nombre, Primer apellido
read et_media en Leer
reads or searches for entries matching the criteria above et_media en lee o busca entradas que coincidan con el criterio indicado arriba
save et_media en Guardar
saves the change to the db et_media en guarda el cambio en la base de datos
select one ... et_media en Seleccionar uno...
select the type fitting most et_media en seleccione el tipo que coincida mejor
type et_media en Tipo
video tape et_media en Cinta de vídeo
we have a fulltext search using that description et_media en tenemos una búsqueda de texto completo usando esa descripción

View File

@ -1,29 +0,0 @@
%d matches on search criteria et_media fr %d occurences sur les critères de recherche
author et_media fr Auteur
book et_media en Book
cancel et_media fr Annuler
clears the form, without changing anything et_media fr Remet à vide le formulaire, sans rien changer
click here to edit the entry et_media fr Cliquez ici pour modifier l'entrée
compact disc et_media en Compact Disc
delete et_media fr Effacer
deletes an entry et_media fr Efface une entrée
description et_media fr Description
dvd et_media en DVD
edit et_media fr Modifier
entry saved et_media fr Entrée enregistrée
error: writeing !!! et_media fr Erreur: à l'écriture !!!
et_media common fr eTemplates MediaDB
etemplates mediadb et_media fr eTemplates MediaDB
here goes the name of the publication / record et_media fr Ici on met le nom de la publication / l'enregistrement
name et_media fr Nom
nothing matched search criteria !!! et_media fr Aucune occurence sur les critères de recherche !!!
please use name, first name et_media fr SVP utilisez nom, prénom
read et_media fr Lire
reads or searches for entries matching the criteria above et_media fr Lit ou recherche des entrées qui correspondent aux critères ci-dessus
save et_media fr Enregistrer
saves the change to the db et_media fr Enregistre les changements dans la base de données
select one ... et_media en Select one ...
select the type fitting most et_media fr Choisissez le type qui correspond le mieux
type et_media fr Type
video tape et_media en Video Tape
we have a fulltext search using that description et_media fr Nous avons une recherche en texte intégral qui utilise cette description

View File

@ -1 +0,0 @@

View File

@ -1,11 +0,0 @@
<?php
// eTemplates for Application 'et_media', generated by etemplate.dump() 2002-10-19 12:21
/* $Id$ */
$templ_data[] = array('name' => 'et_media.edit','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:10:{i:0;a:0:{}i:1;a:4:{s:1:\"A\";a:6:{s:4:\"type\";s:5:\"label\";s:4:\"size\";s:2:\"ib\";s:4:\"span\";s:3:\"all\";s:5:\"label\";s:18:\"eTemplates MediaDB\";s:7:\"no_lang\";s:1:\"1\";s:4:\"name\";s:3:\"msg\";}s:1:\"B\";a:1:{s:4:\"type\";s:5:\"label\";}s:1:\"C\";a:1:{s:4:\"type\";s:5:\"label\";}s:1:\"D\";a:1:{s:4:\"type\";s:5:\"label\";}}i:2;a:4:{s:1:\"A\";a:2:{s:4:\"type\";s:5:\"hrule\";s:4:\"span\";s:3:\"all\";}s:1:\"B\";a:1:{s:4:\"type\";s:5:\"label\";}s:1:\"C\";a:1:{s:4:\"type\";s:5:\"label\";}s:1:\"D\";a:1:{s:4:\"type\";s:5:\"label\";}}i:3;a:4:{s:1:\"A\";a:2:{s:4:\"type\";s:5:\"label\";s:4:\"span\";s:3:\"all\";}s:1:\"B\";a:1:{s:4:\"type\";s:5:\"label\";}s:1:\"C\";a:1:{s:4:\"type\";s:5:\"label\";}s:1:\"D\";a:1:{s:4:\"type\";s:5:\"label\";}}i:4;a:4:{s:1:\"A\";a:2:{s:4:\"type\";s:5:\"label\";s:5:\"label\";s:4:\"Name\";}s:1:\"B\";a:5:{s:4:\"type\";s:4:\"text\";s:4:\"size\";s:7:\"100,100\";s:4:\"span\";s:3:\"all\";s:4:\"name\";s:4:\"name\";s:4:\"help\";s:46:\"here goes the name of the publication / record\";}s:1:\"C\";a:1:{s:4:\"type\";s:5:\"label\";}s:1:\"D\";a:1:{s:4:\"type\";s:5:\"label\";}}i:5;a:4:{s:1:\"A\";a:2:{s:4:\"type\";s:5:\"label\";s:5:\"label\";s:6:\"Author\";}s:1:\"B\";a:5:{s:4:\"type\";s:4:\"text\";s:4:\"size\";s:7:\"100,100\";s:4:\"span\";s:3:\"all\";s:4:\"name\";s:6:\"author\";s:4:\"help\";s:27:\"please use Name, First Name\";}s:1:\"C\";a:1:{s:4:\"type\";s:5:\"label\";}s:1:\"D\";a:1:{s:4:\"type\";s:5:\"label\";}}i:6;a:4:{s:1:\"A\";a:2:{s:4:\"type\";s:5:\"label\";s:5:\"label\";s:4:\"Type\";}s:1:\"B\";a:4:{s:4:\"type\";s:6:\"select\";s:4:\"span\";s:3:\"all\";s:4:\"name\";s:4:\"type\";s:4:\"help\";s:28:\"select the type fitting most\";}s:1:\"C\";a:1:{s:4:\"type\";s:5:\"label\";}s:1:\"D\";a:1:{s:4:\"type\";s:5:\"label\";}}i:7;a:4:{s:1:\"A\";a:2:{s:4:\"type\";s:5:\"label\";s:5:\"label\";s:11:\"Description\";}s:1:\"B\";a:5:{s:4:\"type\";s:8:\"textarea\";s:4:\"size\";s:5:\"3,100\";s:4:\"span\";s:3:\"all\";s:4:\"name\";s:5:\"descr\";s:4:\"help\";s:48:\"we have a fulltext search using that description\";}s:1:\"C\";a:1:{s:4:\"type\";s:5:\"label\";}s:1:\"D\";a:1:{s:4:\"type\";s:5:\"label\";}}i:8;a:4:{s:1:\"A\";a:2:{s:4:\"type\";s:5:\"label\";s:4:\"span\";s:3:\"all\";}s:1:\"B\";a:1:{s:4:\"type\";s:5:\"label\";}s:1:\"C\";a:1:{s:4:\"type\";s:5:\"label\";}s:1:\"D\";a:1:{s:4:\"type\";s:5:\"label\";}}i:9;a:4:{s:1:\"A\";a:4:{s:4:\"type\";s:6:\"button\";s:5:\"label\";s:4:\"Read\";s:4:\"name\";s:4:\"read\";s:4:\"help\";s:57:\"reads or searches for entries matching the criteria above\";}s:1:\"B\";a:4:{s:4:\"type\";s:6:\"button\";s:5:\"label\";s:4:\"Save\";s:4:\"name\";s:4:\"save\";s:4:\"help\";s:26:\"saves the change to the db\";}s:1:\"C\";a:4:{s:4:\"type\";s:6:\"button\";s:5:\"label\";s:6:\"Cancel\";s:4:\"name\";s:6:\"cancel\";s:4:\"help\";s:42:\"clears the form, without changing anything\";}s:1:\"D\";a:4:{s:4:\"type\";s:6:\"button\";s:5:\"label\";s:6:\"Delete\";s:4:\"name\";s:6:\"delete\";s:4:\"help\";s:16:\"deletes an entry\";}}}','size' => '100%','style' => '','modified' => '1014069820',);
$templ_data[] = array('name' => 'et_media.show.rows','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:3:{i:0;a:2:{s:2:\"c1\";s:3:\"nmh\";s:2:\"c2\";s:3:\"nmr\";}i:1;a:3:{s:1:\"A\";a:2:{s:4:\"type\";s:5:\"label\";s:5:\"label\";s:4:\"Name\";}s:1:\"B\";a:2:{s:4:\"type\";s:5:\"label\";s:5:\"label\";s:6:\"Author\";}s:1:\"C\";a:1:{s:4:\"type\";s:5:\"label\";}}i:2;a:3:{s:1:\"A\";a:3:{s:4:\"type\";s:5:\"label\";s:7:\"no_lang\";s:1:\"1\";s:4:\"name\";s:12:\"${row}[name]\";}s:1:\"B\";a:4:{s:4:\"type\";s:5:\"label\";s:4:\"span\";s:5:\",ml10\";s:7:\"no_lang\";s:1:\"1\";s:4:\"name\";s:14:\"${row}[author]\";}s:1:\"C\";a:5:{s:4:\"type\";s:6:\"button\";s:5:\"label\";s:4:\"Edit\";s:5:\"align\";s:6:\"center\";s:4:\"name\";s:19:\"edit[$row_cont[id]]\";s:4:\"help\";s:28:\"click here to edit the entry\";}}}','size' => '100%','style' => '.nmh { font-weight: bold; }','modified' => '1014069820',);
$templ_data[] = array('name' => 'et_media.show','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:5:{i:0;a:0:{}i:1;a:1:{s:1:\"A\";a:6:{s:4:\"type\";s:5:\"label\";s:4:\"size\";s:2:\"ib\";s:4:\"span\";s:3:\"all\";s:5:\"label\";s:18:\"eTemplates MediaDB\";s:7:\"no_lang\";s:1:\"1\";s:4:\"name\";s:3:\"msg\";}}i:2;a:1:{s:1:\"A\";a:2:{s:4:\"type\";s:5:\"hrule\";s:4:\"span\";s:3:\"all\";}}i:3;a:1:{s:1:\"A\";a:2:{s:4:\"type\";s:5:\"label\";s:4:\"span\";s:3:\"all\";}}i:4;a:1:{s:1:\"A\";a:3:{s:4:\"type\";s:8:\"template\";s:4:\"size\";s:5:\"entry\";s:4:\"name\";s:18:\"et_media.show.rows\";}}}','size' => '100%','style' => '','modified' => '1014069820',);

View File

@ -1,42 +0,0 @@
<?php
/**************************************************************************\
* eGroupWare - Editable Templates: Example App of the tutorial *
* http://www.egroupware.org *
" Written by Ralf Becker <RalfBecker@outdoor-training.de> *
* -------------------------------------------- *
* 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$ */
$setup_info['et_media']['name'] = 'et_media';
$setup_info['et_media']['title'] = 'eT-Media';
$setup_info['et_media']['version'] = '1.4';
$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;
$setup_info['et_media']['author'] =
$setup_info['et_media']['maintainer'] = array(
'name' => 'Ralf Becker',
'email' => 'ralfbecker@outdoor-training.de'
);
$setup_info['et_media']['license'] = 'GPL';
$setup_info['et_media']['description'] =
'<b>eTemplates</b> are a new widget-based template system for eGroupWare.<br>
<b>eT-Media</b> is the example application of the eTemplates tutorial.';
$setup_info['et_media']['note'] =
'For more information check out the <a href="etemplate/doc/etemplate.html" target="_blank">Tutorial</a>
and the <a href="etemplate/doc/referenz.html" target="_blank">Referenz Documentation</a>.';
/* Dependencies for this app to work */
$setup_info['et_media']['depends'][] = array(
'appname' => 'phpgwapi',
'versions' => Array('1.2','1.3','1.4','1.5')
);
$setup_info['et_media']['depends'][] = array(
'appname' => 'etemplate',
'versions' => Array('1.2','1.3','1.4','1.5')
);

View File

@ -1,29 +0,0 @@
<?php
/**************************************************************************\
* eGroupWare - Editable Templates: Example App of the tutorial *
* http://www.egroupware.org *
" Written by Ralf Becker <RalfBecker@outdoor-training.de> *
* -------------------------------------------- *
* 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$ */
$phpgw_baseline = array(
'egw_et_media' => array(
'fd' => array(
'id' => array('type' => 'auto','nullable' => False),
'name' => array('type' => 'varchar','precision' => '100','nullable' => False),
'author' => array('type' => 'varchar','precision' => '100','nullable' => False),
'descr' => array('type' => 'text','nullable' => False),
'type' => array('type' => 'varchar','precision' => '20','nullable' => False)
),
'pk' => array('id'),
'fk' => array(),
'ix' => array(),
'uc' => array()
)
);

View File

@ -1,50 +0,0 @@
<?xml version="1.0"?>
<!-- $Id$ -->
<overlay>
<grid id="et_media.edit" template="" lang="" group="" version="" width="100%">
<columns>
<column/>
<column/>
<column/>
<column/>
</columns>
<rows>
<row>
<description options="ib" span="all" value="eTemplates MediaDB" no_lang="1" id="msg"/>
</row>
<row>
<hrule span="all"/>
</row>
<row>
<description span="all"/>
</row>
<row>
<description value="Name"/>
<textbox size="100" maxlength="100" span="all" id="name" statustext="here goes the name of the publication / record"/>
</row>
<row>
<description value="Author"/>
<textbox size="100" maxlength="100" span="all" id="author" statustext="please use Name, First Name"/>
</row>
<row>
<description value="Type"/>
<menulist span="all" statustext="select the type fitting most">
<menupopup id="type"/>
</menulist>
</row>
<row>
<description value="Description"/>
<textbox multiline="true" rows="3" cols="100" span="all" id="descr" statustext="we have a fulltext search using that description"/>
</row>
<row>
<description span="all"/>
</row>
<row>
<button label="Read" id="read" statustext="reads or searches for entries matching the criteria above"/>
<button label="Save" id="save" statustext="saves the change to the db"/>
<button label="Cancel" id="cancel" statustext="clears the form, without changing anything"/>
<button label="Delete" id="delete" statustext="deletes an entry"/>
</row>
</rows>
</grid>
</overlay>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1,24 +0,0 @@
<?xml version="1.0"?>
<!-- $Id$ -->
<overlay>
<grid id="et_media.show.rows" template="" lang="" group="" version="" width="100%">
<columns>
<column/>
<column/>
<column/>
</columns>
<rows>
<row class="nmh">
<description value="Name"/>
<description value="Author"/>
<description/>
</row>
<row class="nmr">
<description no_lang="1" id="${row}[name]"/>
<description class="ml10" no_lang="1" id="${row}[author]"/>
<button label="Edit" align="center" id="edit[$row_cont[id]]" statustext="click here to edit the entry"/>
</row>
</rows>
<styles>.nmh { font-weight: bold; }</styles>
</grid>
</overlay>

View File

@ -1,43 +0,0 @@
<?xml version="1.0"?>
<!-- $Id$ -->
<overlay>
<grid id="et_media.show.rows" template="" lang="" group="0" version="" width="100%">
<columns>
<column/>
<column/>
<column/>
</columns>
<rows>
<row class="nmh">
<description value="Name"/>
<description value="Author"/>
<description/>
</row>
<row class="nmr">
<description no_lang="1" id="${row}[name]"/>
<description class="ml10" no_lang="1" id="${row}[author]"/>
<button label="Edit" align="center" id="edit[$row_cont[id]]" statustext="click here to edit the entry"/>
</row>
</rows>
<styles>.nmh { font-weight: bold; }</styles>
</grid>
<grid id="et_media.show" template="" lang="" group="" version="" width="100%">
<columns>
<column/>
</columns>
<rows>
<row>
<description options="ib" span="all" value="eTemplates MediaDB" no_lang="1" id="msg"/>
</row>
<row>
<hrule span="all"/>
</row>
<row>
<description span="all"/>
</row>
<row>
<grid content="entry" id="et_media.show.rows"/>
</row>
</rows>
</grid>
</overlay>

View File

@ -1,589 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head>
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8"><title>eGroupWare: eTemplates - Templates and Dialog-Editor</title>
<!-- $Id$ -->
<style>
<!--
h1,h2,h3,p,pre { color: black }
pre { border: 1px solid black; padding: 0.08in; font-family: monospace; background: #f0f0f0; }
span { color: darkblue; }
-->
</style></head>
<body>
<h1>eTemplate - Templates and Dialog-Editor for eGroupWare</h1>
<h3>by Ralf Becker <a href="#" onclick="document.location='mai'+'lto:RalfBecker'+unescape('%40')+'outdoor-training'+unescape('%2E')+'de'; return false;">RalfBecker
AT outdoor-training DOT de</a></h3>
<h3>Updated by Raphael Alla <a href="#" onclick="document.location='mai'+'lto:raphael'+unescape('%40')+'olineopensolutions'+unescape('%2E')+'com'; return false;">raphael AT olineopensolutions
DOT com</a></h3>
<p>A developers tutorial how to write an application with the new eTemplates.<br />
It is also an introduction how to write a eGW- and setup(3)-compatible app.</p>
<hr>
<h1>Introduction - The concept of the eTemplates</h1>
<p>The eTemplates
</p>
<ul>
<li>consist out of rows and cols with input-fields of several types</li>
<li>there is a dialog-editor (one part of the etemplate-app) to create the eTemplate</li>
<li>eTemplates can be (and are usually) nested, eg. a template-field can contain an other eTemplate</li>
<li>each field / cell of the template can have a label which is automatically run through lang() (the
content of the field can be run through lang() too)</li>
<li>the dialog editor can write all labels in a lang-file (merging it with the existing ones)</li>
<li>eTemplates have a name of the form app.function[.subtemplate] which is used to call them up</li>
<li>they can have further keys, on loading the class picks the most appropriate one for a user:
<ol>
<li>group: the id of a group if the template is just for that group (that allows admin to show different
views to each group)</li>
<li>lang: the 2 or 5 letter language code (or empty for a non-language specific template)</li>
<li>template set: they belong too (if the template-set key is empty it is an default-template)</li>
<li>version: version number like: '1.3.001'</li>
</ol>
</li>
<li>they are stored in an array and in serialized form in the db-table 'egw_etemplate' </li>
<li>the dialog editor can dump all templates of an app for distribution (so they can be in the CVS too)</li>
<li><p>they encapsulate different UI (User Interface) types from the app: at the moment only a HTML one is ready,
but a GTK one (using <a href="http://gtk.php.net/" target="_blank">php-gtk</a>, <b>running
as native app under Linux and win32</b>) and XUL is under development.<br>Here is a first screenshot of the DB-Tools as native
Linux Application:</li>
</ul>
<img src="gtk.png" name="Graphic1" align="bottom" border="0" height="575" width="1049">
</p>
<hr>
<h1>Tutorial / Example: a simple media database</h1>
<p>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.</p>
<p>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.</p>
<p>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).</p>
<h2>1. Creating a new eGW app directory</h2>
<p>Each app need a name, eg. 'et_media'. We now need to create the
following directory structure above the eGroupWare dir:
</p>
<pre>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</pre><h2>
2. Creating et_media/setup/setup.inc.php</h2>
<p>That files contains the necessary information for setup to install
the app.
</p>
<pre>&lt;?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' =&gt; 'phpgwapi',
'versions' =&gt; Array('1.2','1.3','1.4')
);
$setup_info['et_media']['depends'][] = array(
'appname' =&gt; 'etemplate',
'versions' =&gt; Array('1.2','1.3','1.4')
);</pre><h2>
3. Setting up the db-table with the db_tools and setup</h2>
<p>To enable setup to create a db-table for us and to supply the
<b>so_sql</b>-class with the necessary information, we need to define
the type and size of the fields / columns in our db-table.</p>
<p><br><br>
</p>
<p><img src="dbtools.jpg" name="Graphic2" align="left" border="0" height="340" width="950"><br clear="left"><br>We
can use the db-Tools from the etemplate application to create the
file for us:
</p>
<ol>
<li>start the etemplate app and click on the button up, right which says db-Tools</li>
<li>select Application: eT-Media</li>
<li>type 'egw_et_media' in the field in front of the [Add Table] button and click on the button</li>
<li>now use [Add Column] to create the necessary fields as shown on the screenshot</li>
<li>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)</li>
<li>log out and log into setup and start manage applications</li>
<li>eT-Media is shown as not installed and only install is offered, check it and submit</li>
<li><p>you can now log out from setup, the db-table is now created</li>
<li><p>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)</li>
</ol>
<h2>4. Creating an eTemplates for the edit-dialog</h2>
<p>Now we need a nice edit dialog and use the eTemplate editor to set
it up:
</p>
<ol>
<li>start the etemplate app and type <b>'et_media.edit'</b> in the name field. Save the template in order
to create it</li>
<li>an empty template is displayed. An eTemplate can be thought off as a &quot;grid&quot;. 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:</li>
<li><img src="step0.jpg" name="Graphic3" align="left" border="0" height="509" width="922"><br clear="left">Double
click on the pink spot will bring the following dialog:</li>
<li><img src="step1.jpg" name="Graphic7" align="left" border="0" height="544" width="851"><br clear="left">The
top row allows you to add column and rows to the template. We will need 2 columns and 6 rows</li>
<li>Create the following label in the first top left cell:</li>
</ol>
<img src="step2.jpg" name="Graphic8" align="left" border="0" height="533" width="853"><br clear="left"><br>
</p>
<br>
</p>
<ol start="6">
<li>In the top right cell, we will create a user entry and call it &quot;name&quot;: 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:</li>
<li><img src="step3.jpg" name="Graphic9" align="left" border="0" height="560" width="852"><br clear="left">
<p>Complete the template as follows. The widget used for &quot;type&quot; is a
Selectbox, the one used for &quot;description&quot; is a textarea. Note
that the name of the input is &quot;descr&quot; 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 &quot;Submitbutton&quot; of names &quot;read&quot;
and &quot;save&quot; and of corresponding label.</p>
<p><img src="step4.jpg" name="Graphic4" align="left" border="0" height="380" width="922"><br clear="left"></p>
</li>
</ol>
<p>Then before moving to the next stage save the template as an XML
file by clicking on &quot;Export XML&quot;. Once again the server must have
write permissions on the directory.</p>
<h2>5. Setting up the index page</h2>
<p>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).<br>Create
the file <b>/et_media/index.php</b> with the following content:</p>
<pre>&lt;?php
$GLOBALS['phpgw_info']['flags'] = array(
'currentapp' =&gt; 'et_media',
'noheader' =&gt; True,
'nonavbar' =&gt; True
);
include('../header.inc.php');
$GLOBALS['egw']-&gt;redirect_link('/index.php', 'menuaction=et_media.ui_et_media.edit');
</pre>
<h2>6. The code for our Application</h2>
<p>An eGroupWare application is organized around 3 application
layers:</p>
<ul>
<li>
the storage layer, managed by a &quot;Storage Object&quot; (so).
This object is responsible for handling all access to the storage
engine. We use the "stock" so_sql class for this, so we
need no extra so-object for the moment.
</li>
<li>
the business layer, managed by a &quot;Business Object&quot; (bo).
This object is responsible for all the business logic.
The business object can extend the storage object,
to avoid passing the so-methods as stubs to the ui layer.
</li>
<li>
the user interface layer, managed by a &quot;User Interface&quot;
(ui) object. This object is responsible for all interaction with the
user, including displaying and gathering data to and from the user.
The ui object can extend the bo-object.
</li>
</ul>
<p>For this, we create 2 files in the &quot;inc&quot; 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.</p>
<p>Here is the file <b>/et_media/inc/class.bo_et_media.inc.php</b>:
</p>
<pre>
&lt;?php
<span>/**
* 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 &lt;RalfBecker@outdoor-training.de&gt;
*/</span>
include_once(EGW_INCLUDE_ROOT . '/etemplate/inc/class.so_sql.inc.php');
<span>/**
* Business object for et_media
*/</span>
class bo_et_media extends so_sql
{
<span>/**
* Available media types
*
* @var array
*/</span>
var $types = array(
'' =&gt; 'Select one ...',
'cd' =&gt; 'Compact Disc',
'dvd' =&gt; 'DVD',
'book' =&gt; 'Book',
'video' =&gt; 'Video Tape'
);
<span>/**
* Constructor initializing so_sql
*
* @return so_et_media
*/</span>
function bo_et_media()
{
$this-&gt;so_sql('et_media','egw_et_media'); <span>// calling the constructor of the extended bo object</span>
$this-&gt;empty_on_write = "''";
}
}
</pre>
<p>And finally the start of the
<b>/et_media/inc/class.ui_et_media.inc.php</b>:</p>
<pre>
&lt;?php
<span>/**
* 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 &lt;RalfBecker@outdoor-training.de&gt;
*/</span>
include_once(EGW_INCLUDE_ROOT . '/et_media/inc/class.bo_et_media.inc.php');
class ui_et_media extends bo_et_media
{
<span>/**
* Public functions callable via menuaction
*
* @var array
*/</span>
var $public_functions = array(
'edit' =&gt; True,
);
<span>/**
* Constructor
*
* @return ui_et_media
*/</span>
function ui_et_media()
{
$this-&gt;bo_et_media(); <span>// calling the constructor of the extended bo object</span>
$this-&gt;tmpl =&amp; CreateObject('etemplate.etemplate','et_media.edit');
}
<span>/**
* Edit a media database entry
*
* @param array $content=null
* @param string $msg=''
*/</span>
function edit($content=null,$msg = '')
{
if (is_array($content)) <span>// not first call from index</span>
{
if ($content['id'] &gt; 0)
{
$this-&gt;read($content);
}
<span>//echo "&lt;p&gt;edit: content ="; _debug_array($content);</span>
$this-&gt;data_merge($content);
<span>//echo "&lt;p&gt;edit: data ="; _debug_array($this-&gt;data);</span>
if (isset($content['save']))
{
$msg .= !$this-&gt;save() ? lang('Entry saved') : lang('Error: while saving !!!');
}
}
<span>// now we fill in the content array for the next call to etemplate.exec</span>
$content = $this-&gt;data + array(
'msg' =&gt; $msg
);
$sel_options = array(
'type' =&gt; $this-&gt;types
);
$this-&gt;tmpl-&gt;exec('et_media.ui_et_media.edit',$content,$sel_options,$no_button,array(
'id' =&gt; $this-&gt;data['id']
));
}
</pre>
<p>
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.</p>
<p>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):</p>
<ol>
<li>the $content array is set up with our internal data-array (which is empty on the first call) and the message</li>
<li>$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.</li>
<li>$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)</li>
<li>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.</li>
<li><p>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.</li>
</ol>
<p>Now let's have a look what happens if the user submits the form
and our callback is called:
</p>
<ol>
<li>the callback (this function) is
not the submit-address of the form, the form get's always submitted
to the function <b>process_exec</b> 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. <i>Not all of the is already working, it will
follow in the next days/weeks.</i><br>For the specialist
process_exec uses $_POST and ignores $_GET set as query in the url.</li>
<li>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 (!).</li>
<li>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.</li>
<li>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.</li>
<li>if the search return False we just set our message var.</li>
<li>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.</li>
<li><p>after that the content array is filled again as described above.</li>
</ol>
<p>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.</p>
<p><br>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:</p>
<h2>7. Adding a list-dialog for the search-function</h2>
<p>First we need to create an other eTemplate to show the list:
<b>'et_media.show'</b> as follows. This is made of a label of name
&quot;msg&quot; (to display messages), an HorizontalRule widget, and a
Template widget: we will use a &quot;sub template&quot; called
et_media.show.rows to display the rows of the search function. I have
set the option of the template widget to &quot;entry&quot; as this is the
name we will use to access to the data in the sub-template.
</p>
<p style=""><img src="step5.jpg" name="Graphic5" align="left" border="0" height="561" width="843"><br clear="left"><br><br>
</p>
<p style="">The 'et_media.show.rows' template is
created as a 3x2 table. On the header row, two labels &quot;Name&quot; and
&quot;Author&quot; and one empty cell.</p>
<p>ond row, two labels of name ${row}[name] and ${row}[author]. In the last cell a
submitButton of label &quot;Edit&quot; and of name &quot;edit[$row_cont[id]]&quot;
</p>
<p><img src="step6.jpg" name="Graphic6" align="left" border="0" height="515" width="847"><br clear="left"><br><br>
</p>
<p>The class of the header row is &quot;th&quot; and the class of the
content row is &quot;row&quot;. eTemplate will automatically vary the
colors of the &quot;row&quot; class to provide a nice visual effect.</p>
<p>Here is a view of the et_media.show template once the two
templates have been created:</p>
<p><img src="step7.jpg" name="Graphic10" align="left" border="0" height="419" width="950"><br clear="left"><br><br>
</p>
<p>We need some code / a function in the class to call the template
and fill the content:</p>
<pre>
<span>/**
* Showing entries from the media database
*
* @param array $found
*/</span>
function show($found=null)
{
if (!is_array($found) || !count($found))
{
$this-&gt;edit();
return;
}
array_unshift($found,false); <span>// change the array to start with index 1</span>
$content = array(
'msg' =&gt; lang('%1 matches on search criteria',count($found)-1),
'entry' =&gt; $found,
);
$this-&gt;tmpl-&gt;read('et_media.show');
$this-&gt;tmpl-&gt;exec('et_media.ui_et_media.edit',$content);
}
}
</pre><p>
This function is called by edit with the matches of a search:</p>
<ol>
<li>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).<br />
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.</li>
<li>$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).</li>
<li>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)</li>
<li>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).</li>
</ol>
<p>To call the show function, we need to make some changes to the
edit-function too:</p>
<pre>
elseif (isset($content['read']))
{
unset($content['id']); <span>// not set by user, so don't use for search</span>
unset($content['read']);
$found = $this-&gt;search($content,False,'name,author'); <span>// searches by using the no-empty fields</span>
if (!$found)
{
$msg .= lang('Nothing matched search criteria !!!');
}
elseif (count($found) == 1)
{
$this-&gt;init($found[0]); <span>// only one match --&gt; show it in the editor</span>
}
else
{
$this-&gt;show($found); <span>// multiple matches --&gt; use the show function/template</span>
return;
}
}
elseif (isset($content['entry']['edit'])) <span>// the callback from for the show function/template</span>
{ <span>// the id is set via the button name of '$row_cont[id]'</span>
list($id) = each($content['entry']['edit']); <span>// note its not only ['edit'] !!!</span>
if ($id &gt; 0)
{
$this-&gt;read(array('id' =&gt; $id));
}
}
</pre>
<ol>
<li>the first part should be self-explaining, we call show with $found if it contain more than
one entry.</li>
<li>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.</li>
</ol>
<p>This is what the new &quot;show&quot; template looks like:</p>
<p><img src="step8.jpg" name="Graphic11" align="left" border="0" height="349" width="950"><br clear="left"><br><br>
</p>
<p>While making these changes we can add a [Cancel] and [Delete]
button too:</p>
<pre>
elseif (isset($content['cancel']))
{
$content = array(); <span>// clear the contents</span>
}
elseif (isset($content['delete']))
{
$this-&gt;bo-&gt;so-&gt;delete($r_id);
$content = array(); <span>// clear the content</span>
}
$no_button = array( <span>// no delete button if id == 0 --&gt; entry not saved</span>
'delete' =&gt; !$this-&gt;content['id'];
);
</pre>
<ol>
<li>on cancel we just clear the internal data-array with so_sql's init function.</li>
<li>on delete we have to call so_sql's delete before (it deletes the db-row corresponding
with our internal data-array)</li>
<li><p>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-&gt;db_key_cols[$this-&gt;autoinc_id] == 'id').</li>
</ol>
<p>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 ;-).</p>
<p>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 <a href="#etFile">Dumping the eTemplate to a File for Distribution</a>.
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.</p>
<h2>8. Creating the English lang-file</h2>
<p>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<br>There are 2 possibilities to create it automatically:</p>
<ol>
<li>Use the [Write Langfile] button in the eTemplate editor (put the app-name 'et_media' in the name-field
first)<br />That will NOT write the messages in the classes!!!</li>
<li>We can use the TranslationTools to scans our sources for lang('...') calls ([search new phrases] button).</li>
<li>Other phrases like the media types can be added manually via [Add] button in the Translation Tools.</li>
</ol>
<a name="etFile" /><h2>9. Dumping the eTemplate to a File for Distribution</h2>
<p>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.
</p>
<p>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
<b>et_media/setup/etemplates.inc.php</b>. The eTemplate-class loads
this file whenever it finds a new version automatically.</p>
<p>To recover a changed eTemplate to the state saved in the distribution file, the following
steps need to be performed:</p>
<ul>
<li>Remove the modified template (or the modified version of the template)
in the eTemplate application</li>
<li>Touch the setup/etemplates.inc.php file in the application directory
(update it's timestamp).</li>
</ul>
<p>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.</p>
<h2>10. Further information</h2>
<p><b>Please note:</b> <i>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.</i></p>
<ol>
<li>the <a href="reference.html">reference-documentation</a> of the eTemplates</li>
<li>for all functions and parameters of the <b>etemplate</b>-class(es) look in the
<a href="http://www.egroupware.org/egwdoc/li_etemplate.html" target="_blank">phpDocumentor docu of etemplate</a>
created from comments (yes there are comments) in the sources:
<ul>
<li><a href="http://www.egroupware.org/egwdoc/etemplate/api/etemplate.html" target="_blank">class.uietemplate.inc.php</a>
for the exec function</p></li>
<li><a href="http://www.egroupware.org/egwdoc/etemplate/api/boetemplate.html" target="_blank">class.boetemplate.inc.php</a>
for the variable replacement in names and about the autorepeat rows and columns</p></li>
<li><a href="http://www.egroupware.org/egwdoc/etemplate/api/boetemplate.html" target="_blank">class.soetemplate.inc.php</a>
for writeLangFile and all functions to read, store and dump an eTemplate</p></li>
</ul>
</li>
<li>for all functions and parameters of the <b>so_sql</b>-class look in the comments of the file
<a href="http://www.egroupware.org/egwdoc/etemplate/api/so_sql.html" target="_blank">class.so_sql.inc.php</a></li>
<li><p>for setup, the necessary files of an app or the format of
tables_current.inc.php look at the excellent <a href="../../setup/doc/setup3.html">docu
of setup3</a> in the doc-dir of the setup app. </li>
</ol>
<h2><i>That's it</i> - please write to our <a href="#"
onclick="document.location='mai'+'lto:egroupware-developer'+unescape('%40')+'lists'+unescape('%2E')+'sf.net'; return false;">developers
list</a> or <a href="http://forum.egroupware.org/" target="_blank">developer forum</a>,
if you have further questions or comments about the tutorial or eTemplate.</h2>
</body></html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

View File

@ -1,32 +0,0 @@
<?php
/*
* Egroupware
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage api
* @link http://www.egroupware.org
* @author Nathan Gray
* @version $Id$
*/
$GLOBALS['egw_info'] = array(
'flags' => array(
'currentapp' => 'projectmanager',
'noheader' => True,
'nonavbar' => True
));
include('../header.inc.php');
egw_framework::csp_script_src_attrs(array('https://export.dhtmlx.com/gantt/api.js'));
egw_framework::csp_connect_src_attrs('http://export.dhtmlx.com');
egw_framework::validate_file('/api/js/dhtmlxtree/codebase/dhtmlxcommon.js');
egw_framework::validate_file('/api/js/dhtmlxGantt/codebase/dhtmlxgantt.js');
egw_framework::includeCSS('/api/js/dhtmlxGantt/codebase/dhtmlxgantt.css');
echo $GLOBALS['egw']->framework->header();
?>
<?php
?>

File diff suppressed because it is too large Load Diff

View File

@ -1,474 +0,0 @@
<?php
/**
* eGroupWare eTemplate Extension - AJAX Select Widget
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage extensions
* @link http://www.egroupware.org
* @author Nathan Gray <nathangray@sourceforge.net>
* @version $Id$
*/
use EGroupware\Api;
/**
* AJAX Select Widget
*
* Using AJAX, this widget allows a type-ahead find similar to a ComboBox, where as the user enters information,
* a drop-down box is populated with the n closest matches. If the user clicks on an item in the drop-down, that
* value is selected.
* n is the maximum number of results set in the user's preferences.
* The user is restricted to selecting values in the list.
* This widget can get data from any function that can provide data to a nextmatch widget.
* This widget is generating html, so it does not work (without an extra implementation) in an other UI
*/
class ajax_select_widget
{
var $public_functions = array(
'pre_process' => True,
'post_process' => True,
'ajax_search' => True,
);
var $human_name = 'AJAX Select'; // this is the name for the editor
// Accepted option keys if you're passing in an array to set up the widget
// Additional options will be passed to the search query
public static $known_options = array(
// These ones can be passed in from eTemplate editor in size
'get_rows',
'get_title',
'id_field',
'template',
'filter',
'filter2',
'link',
'icon',
// Pass by code only
'values',
);
// Flag used in id_field to indicate that the key of the record should be used as the value
const ARRAY_KEY = 'array_key';
// Array of static values to emulate a combo-box, with no DB lookup
protected static $static_values = array();
private $debug = false;
function __construct($ui='')
{
switch($ui)
{
case '':
case 'html':
$this->ui = 'html';
break;
default:
echo "UI='$ui' not implemented";
}
return 0;
}
/**
* pre-processing of the extension
*
* This function is called before the extension gets rendered
*
* @param string $name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param object &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process($name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl)
{
if($this->debug) {
echo __METHOD__ . '<br />';
printf("Name:%20s<br />", $name);
echo 'Value:';
_debug_array($value);
echo 'Cell:';
_debug_array($cell);
echo 'Readonlys:';
_debug_array($readonlys);
echo 'Extension_data:';
_debug_array($extension_data);
}
// Get Options
$options = array();
if(!is_array($cell['size'])) {
list(
$options['get_rows'],
$options['get_title'],
$options['id_field'],
$options['template'],
$options['filter'],
$options['filter2'],
$options['link'],
$options['icon']
) = explode(',', $cell['size']);
} else {
$options = $cell['size'];
}
if(is_array($value)) {
$options = array_merge($options, $value);
}
if(!$options['template']) {
$options['template'] = 'etemplate.ajax_select_widget.row';
}
if(array_key_exists('values', $options)) {
if($options['values']) {
self::$static_values[$name] = $options['values'];
}
unset($options['values']);
}
$onchange = ($cell['onchange'] ? $cell['onchange'] : 'false');
// Set current value
if(!is_array($value)) {
$current_value = $value;
} elseif($value[$options['id_field']]) {
$current_value = $value[$options['id_field']];
}
$extension_data['old_value'] = $value;
list($title_app, $title_class, $title_method) = explode('.', $options['get_title']);
if($title_app && $title_class) {
if (is_object($GLOBALS[$title_class])) { // use existing instance (put there by a previous CreateObject)
$title_obj =& $GLOBALS[$title_class];
} else {
$title_obj =& CreateObject($title_app . '.' . $title_class);
}
}
if(!is_object($title_obj) || !method_exists($title_obj,$title_method)) {
echo "$entry_app.$entry_class.$entry_method is not a valid method for getting the title";
} elseif($current_value) {
if($title_method == 'array_title' && $title_class == __CLASS__) {
$title = self::$title_method($current_value, $name);
} else {
$title = $title_obj->$title_method($current_value);
}
}
// Check get_rows method
list($get_rows_app, $get_rows_class, $get_rows_method) = explode('.', $options['get_rows']);
if($get_rows_app && $get_rows_class) {
if (is_object($GLOBALS[$get_rows_class])) { // use existing instance (put there by a previous CreateObject)
$get_rows_obj =& $GLOBALS[$get_rows_class];
} else {
$get_rows_obj =& CreateObject($get_rows_app . '.' . $get_rows_class);
}
if(!is_object($get_rows_obj) || !method_exists($get_rows_obj, $get_rows_method)) {
echo "$get_rows_app.$get_rows_class.$get_rows_method is not a valid method for getting the rows";
}
}
// Set up widget
$cell['type'] = 'template';
$cell['size'] = $cell['name'];
$value = array('value' => $current_value, 'search' => $title);
$widget = new etemplate('etemplate.ajax_select_widget');
$widget->no_onclick = True;
// Link if readonly & link is set
$search =& $widget->get_widget_by_name('search');
if(($cell['readonly'] || $readonlys['search']) && $options['link']) {
$cell['readonly'] = false;
if(!is_array($readonlys)) {
$readonlys = array('search' => true);
} else {
$readonlys['search'] = true;
}
$search['type'] = 'label';
$search['no_lang'] = 1;
$search['size'] = ',' . $options['link'];
$extension_data['readonly'] = true;
} else {
$search['type'] = 'text';
$search['size'] = '';
if($current_value == '' && $options['id_field'] == self::ARRAY_KEY) {
$search['blur'] = lang('Search...');
}
}
// Icon
$icon =& $widget->get_widget_by_path('/0/1A');
$icon['name'] = $options['icon'];
$cell['obj'] = &$widget;
// Save static values, if set
if(self::$static_values[$name]) {
$extension_data['values'] = self::$static_values[$name];
}
// Save options for post_processing
$extension_data['options'] = $options;
$extension_data['needed'] = $cell['needed'];
// xajax
$GLOBALS['egw_info']['flags']['include_xajax'] = True;
// JavaScript
// converter doesn't handle numeric well
foreach($options as $key => &$value) {
if(is_numeric($value)) {
$value = (string)$value;
}
if($value === null) {
unset($options[$key]);
}
}
$options = json_encode($options);
$GLOBALS['egw']->js->set_onload("if(!options) {
var options = new Object();
}\n
options['$name'] = $options;
ajax_select_widget_setup('$name', '$onchange', options['$name'], '" . $GLOBALS['egw_info']['flags']['currentapp'] . "');
");
$GLOBALS['egw']->js->validate_file('.', 'ajax_select', 'etemplate');
return True; // no extra label
}
function post_process($name,&$value,&$extension_data,&$loop,&$tmpl,$value_in)
{
//echo "<p>ajax_select_widget.post_process: $name = "; _debug_array($value_in);_debug_array($extension_data);
if(!is_array($value_in)) {
$value_in = $extension_data['old_value'];
}
// Check for blur text left in
if($value_in['search'] == lang('Search...') ) {
$value_in['search'] = '';
}
// They typed something in, but didn't choose a result
if(!$value_in['value'] && $value_in['search']) {
list($get_rows_app, $get_rows_class, $get_rows_method) = explode('.', $extension_data['options']['get_rows']);
if($get_rows_app && $get_rows_class) {
if (is_object($GLOBALS[$get_rows_class])) { // use existing instance (put there by a previous CreateObject)
$get_rows_obj =& $GLOBALS[$get_rows_class];
} else {
$get_rows_obj =& CreateObject($get_rows_app . '.' . $get_rows_class);
}
if(!is_object($get_rows_obj) || !method_exists($get_rows_obj, $get_rows_method)) {
echo "$get_rows_app.$get_rows_class.$get_rows_method is not a valid method for getting the rows";
} else {
$query = array_merge($extension_data['options'], $value_in);
$count = $get_rows_obj->$get_rows_method($query, $results, $readonlys=array());
if($count == 1) {
$value = $results[0][$extension_data['options']['id_field']];
return true;
} elseif ($count > 1) {
etemplate::set_validation_error($name,lang("More than 1 match for '%1'",$value_in['search']));
$loop = true;
return false;
} else {
$value = $value_in['search'];
return true;
}
}
}
} elseif ($extension_data['readonly']) {
$value = $extension_data['old_value'];
return true;
} elseif ($value_in['search'] == '') {
// They're trying to clear the form
$value = null;
// True if not needed, false if needed and they gave no value
$return = !($extension_data['needed'] && trim($value_in['value']) == '');
if(!$return) {
$value = $extension_data['old_value'];
etemplate::set_validation_error($name,lang('Required'));
$loop = true;
}
if($this->debug && $loop) {
echo 'Looping...<br />Returning ' . $return . '<br />';
}
return $return;
} else {
if (stripos($extension_data['options']['id_field'], ";")) {
$expected_fields = array_flip(explode(";", $extension_data['options']['id_field']));
$fields_n_values = explode(";", $value_in['value']);
foreach ($fields_n_values as $field_n_value) {
list($myfield, $myvalue) = explode(":", $field_n_value);
if (array_key_exists($myfield, $expected_fields)) {
$value_in[$myfield] = $myvalue;
}
}
$value = $value_in;
} else {
$value = $value_in['value'];
}
return true;
}
}
function ajax_search($id, $value, $set_id, $query, $etemplate_id) {
$base_id = substr($id, 0, strrpos($id, '['));
$result_id = ($set_id ? $set_id : $base_id . '[results]');
$response = new xajaxResponse();
if($query['get_rows']) {
list($app, $class, $method) = explode('.', $query['get_rows']);
$this->bo = CreateObject($app . '.' . $class);
unset($query['get_rows']);
} else {
return $response->getXML();
}
// Expand lists
foreach($query as $key => &$row) {
if($row && strpos($row, ',')) {
$query[$key] = explode(',', $row);
}
// sometimes it sends 'null' (not null)
if($row == 'null') {
unset($query[$key]);
} elseif (is_string($row) && strtolower($row) == 'false') {
$row = false;
}
}
$query['search'] = $value;
if($query['id_field'] == self::ARRAY_KEY) {
// Pass base_id so we can get the right values
$query['field_name'] = $base_id;
// Check for a provided list of values
if(($request = Api\Etemplate\Request::read($etemplate_id))) {
$extension_data = $request->extension_data[$base_id];
if(is_array($extension_data) && $extension_data['values']) {
self::$static_values[$base_id] = $extension_data['values'];
}
}
}
$result_list = array();
$readonlys = array();
if(is_object($this->bo)) {
$count = $this->bo->$method($query, $result_list, $readonlys);
}
if(is_array($count)) {
$count = count($result_list);
}
$response->addScript("remove_ajax_results('$result_id')");
if($count > 0) {
$response->addScript("add_ajax_result('$result_id', '', '', '" . lang('Select') ."');");
$count = 0;
if(!$query['template'] || $query['template'] == 'etemplate.ajax_select_widget.row') {
$query['template'] = 'etemplate.ajax_select_widget.row';
}
foreach($result_list as $key => &$row) {
if(!is_array($row)) {
if($query['id_field'] == self::ARRAY_KEY) {
if(!is_array($row)) {
// Restructure $row to be an array
$row = array(
self::ARRAY_KEY => $key,
'id_field' => $key,
'title' => $row
);
}
} else {
continue;
}
}
//check for multiple id's
//this if control statement is to determine if there are multiple ids in the ID FIELD of the Ajax Widget
if(stristr($query['id_field'], ';') != FALSE) {
$id_field_keys = explode(';', $query['id_field']);
if($query['get_title']) {
//the title will always be created using the first ID FIELD
if($row[$id_field_keys[0]]) {
$row['title'] = ExecMethod($query['get_title'], $row[$id_field_keys[0]]);
}
}
foreach($id_field_keys as $value) {
$id_field_keys_values[] = $value.':'.$row[$value];
}
$row['id_field'] = implode(';',$id_field_keys_values);
unset($id_field_keys_values);
} else {
if($query['id_field'] && $query['get_title']) {
if($row[$query['id_field']] && $query['id_field'] != self::ARRAY_KEY) {
$row['title'] = ExecMethod($query['get_title'], $row[$query['id_field']]);
}
}
if($query['id_field'] != self::ARRAY_KEY) {
$row['id_field'] = $row[$query['id_field']];
}
}
// If we use htmlspecialchars, it causes issues with mixed quotes. addslashes() seems to handle it.
$row['id_field'] = addslashes($row['id_field']);
$data = ($query['nextmatch_template']) ? array(1=>$row) : $row;
$widget =& CreateObject('etemplate.etemplate', $query['template']);
$html = addslashes(str_replace("\n", '', $widget->show($data, '', $readonlys)));
$row['title'] = addslashes($row['title']);
$response->addScript("add_ajax_result('$result_id', '${row['id_field']}', '" . $row['title'] . "', '$html');");
$count++;
if($count > $GLOBALS['egw_info']['user']['preferences']['common']['maxmatchs']) {
$response->addScript("add_ajax_result('$result_id', '', '', '" . lang("%1 more...", (count($result_list) - $count)) . "');");
break;
}
}
} else {
$response->addScript("add_ajax_result('$result_id', '', '', '" . lang('No matches found') ."');");
}
return $response->getXML();
}
/**
* Use a simple array to get the title
* Values should be passed in to the widget as an array in $size['values']
*/
protected function array_title($id, $name) {
if(trim($id) == '') {
return lang('Search');
}
return self::$static_values[$name][$id];
}
/**
* Use a simple array to get the results
* Values should be passed in to the widget as an array in $size['values']
*/
protected function array_rows(&$query, &$result) {
foreach( self::$static_values[$query['field_name']] as $key => $value) {
if($query['search'] && stripos($value, $query['search']) === false) continue;
$result[$key] = $value;
}
$count = count($result);
$result = array_slice($result, $query['start'], $query['num_rows']);
return $count;
}
}

View File

@ -1,21 +0,0 @@
<?php
/**
* EGroupware - Document merge print
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @package api
* @subpackage storage
* @copyright (c) 2007-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
use EGroupware\Api\Storage\Merge;
/**
* Document merge print
*
* @deprecated use Api\Storage\Merge
*/
abstract class bo_merge extends Merge {}

View File

@ -1,23 +0,0 @@
<?php
/**
* EGroupware - abstract base class for tracking (history log, notifications, ...)
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @package etemplate
* @subpackage api
* @copyright (c) 2007-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
use EGroupware\Api;
/**
* Abstract base class for trackering:
* - logging all modifications of an entry
* - notifying users about changes in an entry
*
* @deprecated use Api\Storage\Tracking
*/
abstract class bo_tracking extends Api\Storage\Tracking {}

File diff suppressed because it is too large Load Diff

View File

@ -1,243 +0,0 @@
<?php
/**
* EGroupware - TranslationTools
*
* @link http://www.egroupware.org
* @author Miles Lott <milos(at)groupwhere.org>
* @author Ralf Becker <RalfBecker(at)outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage translationtools
* @version $Id$
*/
class bolangfile
{
var $total;
var $debug = False;
/**
* storage object
*
* @var solangfile
*/
var $so;
var $loaded_apps = array();
var $source_langarray = '';
var $missing_langarray = '';
var $target_langarray = '';
var $extra_langarray = array();
var $src_file;
var $src_apps = array();
var $tgt_file;
var $tgt_lang;
function __construct()
{
$this->so = new solangfile(); // is now in etemplate, to not doublicate it
}
/* Sessions used to save state and not reread the langfile between adding/deleting phrases */
function save_sessiondata($source='##unset##',$target='##unset##')
{
if ($source == '##unset##')
{
$source = &$this->source_langarray;
}
if ($target == '##unset##')
{
$target = &$this->target_langarray;
}
if($this->debug) { echo '<br>Save:'; _debug_array($source); }
$GLOBALS['egw']->session->appsession('developer_source_lang','developer_tools',$source);
if($this->debug) { echo '<br>Save:'; _debug_array($target); }
$GLOBALS['egw']->session->appsession('developer_target_lang','developer_tools',$target);
$GLOBALS['egw']->session->appsession('developer_source_file','developer_tools',$this->src_file);
$GLOBALS['egw']->session->appsession('developer_target_file','developer_tools',$this->tgt_file);
$GLOBALS['egw']->session->appsession('developer_t_lang','developer_tools',$this->tgt_lang);
$GLOBALS['egw']->session->appsession('developer_loaded_apps','developer_tools',$this->loaded_apps);
$GLOBALS['egw']->session->appsession('developer_src_apps','developer_tools',$this->src_apps);
$GLOBALS['egw']->session->appsession('developer_missing_lang','developer_tools',$this->missing_langarray);
}
function read_sessiondata()
{
$source = $GLOBALS['egw']->session->appsession('developer_source_lang','developer_tools');
if($this->debug) { echo '<br>Read:'; _debug_array($source); }
$target = $GLOBALS['egw']->session->appsession('developer_target_lang','developer_tools');
if($this->debug) { echo '<br>Read:'; _debug_array($target); }
$src_file = $GLOBALS['egw']->session->appsession('developer_source_file','developer_tools');
$tgt_file = $GLOBALS['egw']->session->appsession('developer_target_file','developer_tools');
$tgt_lang = $GLOBALS['egw']->session->appsession('developer_t_lang','developer_tools');
$loaded_apps = $GLOBALS['egw']->session->appsession('developer_loaded_apps','developer_tools');
$src_apps = $GLOBALS['egw']->session->appsession('developer_src_apps','developer_tools');
$missing = $GLOBALS['egw']->session->appsession('developer_missing_lang','developer_tools');
$this->set_sessiondata($source,$target,$src_file,$tgt_file,$tgt_lang,$loaded_apps,$src_apps,$missing);
}
function set_sessiondata($source,$target,$src_file,$tgt_file,$tgt_lang,$loaded_apps,$src_apps,$missing)
{
$this->source_langarray = $source;
$this->target_langarray = $target;
$this->src_file = $src_file;
$this->tgt_file = $tgt_file;
$this->tgt_lang = $tgt_lang;
$this->loaded_apps = $loaded_apps;
$this->src_apps = $src_apps;
$this->missing_langarray = $missing;
}
function clear_sessiondata()
{
$GLOBALS['egw']->session->appsession('developer_source_lang','developer_tools','');
$GLOBALS['egw']->session->appsession('developer_target_lang','developer_tools','');
$GLOBALS['egw']->session->appsession('developer_source_file','developer_tools','');
$GLOBALS['egw']->session->appsession('developer_target_file','developer_tools','');
$GLOBALS['egw']->session->appsession('developer_t_lang','developer_tools','');
$GLOBALS['egw']->session->appsession('developer_loaded_apps','developer_tools','');
}
function addphrase($entry)
{
/* _debug_array($this->source_langarray);exit; */
if (empty($entry['content'])) $entry['content'] = $entry['message_id'];
$mess_id = strtolower(trim($entry['message_id']));
$this->source_langarray[$mess_id] = array(
'message_id' => $mess_id,
'content' => $entry['content'],
'app_name' => $entry['app_name'] == 'phpgwapi' ? 'common' : $entry['app_name'],
'lang' => 'en'
);
@ksort($this->source_langarray);
if (!empty($entry['target']))
{
$this->target_langarray[$mess_id] = array(
'message_id' => $mess_id,
'content' => $entry['target'],
'app_name' => $entry['app_name'] == 'phpgwapi' ? 'common' : $entry['app_name'],
'lang' => $this->tgt_lang
);
}
}
function movephrase($mess='')
{
if ($mess !='' && ($this->missing_langarray[$mess]['message_id']))
{
$this->source_langarray[$mess] = $m = array(
'message_id' => $this->missing_langarray[$mess]['message_id'],
'content' => $this->missing_langarray[$mess]['content'],
'app_name' => $this->missing_langarray[$mess]['app_name'],
'lang' => 'en'
);
@ksort($this->source_langarray);
reset($this->source_langarray);
if ($this->tgt_lang == 'en')
{
$this->target_langarray[$mess] = $m;
@ksort($this->target_langarray);
reset($this->target_langarray);
}
}
//else echo "'$mess' not found in missing_langarray !!!<br>\n";
}
function missing_app($app,$userlang='en')
{
$this->missing_langarray = array();
if (!is_array($this->extra_langarray['common']))
{
$this->extra_langarray['common'] = $this->so->load_app('phpgwapi',$userlang);
}
$plist = $this->so->missing_app($app = trim($app),$userlang);
foreach($plist as $p => $loc)
{
$_mess_id = strtolower(trim($p));
if ($loc != $app)
{
if (!is_array($this->extra_langarray[$loc]))
{
$this->extra_langarray[$loc] = $this->so->load_app($loc,$userlang);
//echo "<p>loading translations for '$loc'</p>\n";
}
}
if (!empty($_mess_id) && !$this->source_langarray[$_mess_id] &&
!$this->extra_langarray['common'][$_mess_id] &&
($app == $loc || !$this->extra_langarray[$loc][$_mess_id]))
{
//echo "Havn't found '$_mess_id'/$loc !!!<br>\n";
$this->missing_langarray[$_mess_id] = array(
'message_id' => $_mess_id,
'app_name' => $loc,
'content' => $p
);
}
}
if (is_array($this->missing_langarray))
{
reset ($this->missing_langarray);
@ksort($this->missing_langarray);
}
return $this->missing_langarray;
}
function add_app($app,$userlang='en')
{
if(gettype($this->source_langarray) == 'array')
{
return $this->source_langarray;
}
$this->source_langarray = $this->so->load_app($app,$userlang,False);
$this->src_file = $this->so->src_file;
$this->loaded_apps = $this->so->loaded_apps;
$this->src_apps = $this->so->src_apps;
return $this->source_langarray;
}
function load_app($app,$userlang='en')
{
if(gettype($this->target_langarray) == 'array')
{
if ($this->tgt_lang == $userlang)
{
return $this->target_langarray;
}
}
$this->target_langarray = $this->so->load_app($app,$userlang);
$this->tgt_file = $this->so->tgt_file;
$this->tgt_lang = $userlang;
$this->loaded_apps = $this->so->loaded_apps;
return $this->target_langarray;
}
function write_file($which,$app_name,$userlang)
{
switch ($which)
{
case 'source':
$this->src_file = $this->so->write_file($app_name,$this->source_langarray,$userlang,$which);
break;
case 'target':
// removing phrases not in the source language
$before = count($this->target_langarray);
$this->target_langarray = array_intersect_assoc($this->target_langarray,$this->source_langarray);
if ($before > ($after = count($this->target_langarray)))
{
echo '<br />'. lang('Removed %1 phrases from the target language, as they are not present in the source language!',$before-$after)."\n";
}
$this->tgt_file = $this->so->write_file($app_name,$this->target_langarray,$userlang,$which);
break;
default:
break;
}
$this->save_sessiondata();
}
}

View File

@ -1,139 +0,0 @@
<?php
/**
* EGroupware eTemplate Extension - Contact Widget
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage extensions
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/
use EGroupware\Api\Etemplate\Widget\Contact;
/**
* eTemplate Extension: Contact widget
*
* This widget can be used to fetch fields of a contact specified by contact-id
*/
class contact_widget extends Contact
{
/**
* exported methods of this class
*
* @var array $public_functions
* @deprecated only used for old etemplate
*/
public $public_functions = array(
'pre_process' => True,
);
/**
* availible extensions and there names for the editor
*
* @var string|array $human_name
* @deprecated only used for old etemplate
*/
public $human_name = array(
'contact-value' => 'Contact',
'contact-account' => 'Account contactdata',
'contact-template' => 'Account template',
'contact-fields' => 'Contact fields',
);
/**
* pre-processing of the extension
*
* This function is called before the extension gets rendered
*
* @param string $name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param etemplate &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process($name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl)
{
unset($readonlys, $extension_data); // not used, but required by function signature
//echo "<p>contact_widget::pre_process('$name','$value',".print_r($cell,true).",...)</p>\n";
switch($type = $cell['type'])
{
case 'contact-fields':
$cell['sel_options'] = $this->get_contact_fields();
$cell['type'] = 'select';
$cell['no_lang'] = 1;
$cell['size'] = 'None';
break;
case 'contact-account':
case 'contact-template':
if (substr($value,0,8) != 'account:')
{
$value = 'account:'.($cell['name'] != 'account:' ? $value : $GLOBALS['egw_info']['user']['account_id']);
}
echo "<p>$name: $value</p>\n";
// fall-throught
case 'contact-value':
default:
if (substr($value,0,12) == 'addressbook:') $value = substr($value,12); // link-entry syntax
if (!$value || !$cell['size'] || (!is_array($this->contact) ||
!($this->contact['id'] == $value || 'account:'.$this->contact['account_id'] == $value)) &&
!($this->contact = $this->contacts->read($value)))
{
$cell = $tmpl->empty_cell();
$value = '';
break;
}
$type = $cell['size'];
$cell['size'] = '';
if ($cell['type'] == 'contact-template')
{
$name = $this->contact[$type];
$cell['type'] = 'template';
if (($prefix = $cell['label'])) $name = strpos($prefix,'%s') !== false ? str_replace('%s',$name,$prefix) : $prefix.$name;
$cell['obj'] = new etemplate($name,$tmpl->as_array());
return false;
}
$value = $this->contact[$type];
$cell['no_lang'] = 1;
$cell['readonly'] = true;
switch($type)
{
// ToDo: pseudo types like address-label
case 'bday':
$cell['type'] = 'date';
$cell['size'] = 'Y-m-d';
break;
case 'owner':
case 'modifier':
case 'creator':
$cell['type'] = 'select-account';
break;
case 'modified':
case 'created':
$cell['type'] = 'date-time';
break;
case 'cat_id':
$cell['type'] = 'select-cat';
break;
default:
$cell['type'] = 'label';
break;
}
break;
}
$cell['id'] = ($cell['id'] ? $cell['id'] : $cell['name'])."[$type]";
return True; // extra label ok
}
}

View File

@ -1,530 +0,0 @@
<?php
/**
* EGroupware eTemplate Widget for custom fields
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @author Cornelius Weiss <egw@von-und-zu-weiss.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage extensions
* @version $Id$
*/
/**
* This widget generates a template for customfields based on definitions in egw_config table
*
* All widgets here have 2+ comma-separated options ($cell[size]):
* - sub-type to display only the cf's without subtype or with a matching one
* - use-private to display only (non-)private cf's (0=regular ones, 1=private ones, default both)
* - field-name to display only the named custom field(s). Use ! before to display all but given field(s).
* Additional fields can be added with a comma between them
*
* Private cf's the user has no right to see (neither him nor his memberships are mentioned) are never displayed.
*/
class customfields_widget
{
var $public_functions = array(
'pre_process' => True,
);
var $human_name = array(
'customfields' => 'custom fields',
'customfields-types' => 'custom field types',
'customfields-list' => 'custom field list',
'customfields-no-label' => 'custom fields without label',
);
/**
* Allowd types of customfields
*
* The additionally allowed app-names from the link-class, will be add by the edit-method only,
* as the link-class has to be called, which can NOT be instanciated by the constructor, as
* we get a loop in the instanciation.
*
* @var array
*/
var $cf_types = array(
'text' => 'Text',
'int' => 'Integer',
'float' => 'Float',
'label' => 'Label',
'select' => 'Selectbox',
'ajax_select' => 'Search',
'radio' => 'Radiobutton',
'checkbox' => 'Checkbox',
'date' => 'Date',
'date-time'=> 'Date+Time',
'select-account' => 'Select account',
'button' => 'Button', // button to execute javascript
'url' => 'Url',
'url-email'=> 'EMail',
'url-phone'=> 'Phone number',
'htmlarea' => 'Formatted Text (HTML)',
'link-entry' => 'Select entry', // should be last type, as the individual apps get added behind
);
/**
* @var $prefix string Prefix for every custiomfield name returned in $content (# for general (admin) customfields)
*/
var $prefix = '#';
/**
* Current application
*
* @var string
*/
var $appname;
/**
* Instance of the config class for $appname
*
* @var config
*/
var $config;
/**
* Our customfields as name => data array
*
* @var array
*/
var $customfields;
var $types;
var $advanced_search;
function __construct($ui=null,$appname=null)
{
$this->appname = $appname ? $appname : $GLOBALS['egw_info']['flags']['currentapp'];
$this->customfields = egw_customfields::get($this->appname);
$this->types = config::get_content_types($this->appname);
$this->advanced_search = $GLOBALS['egw_info']['etemplate']['advanced_search'];
}
/**
* pre-processing of the extension
*
* This function is called before the extension gets rendered
*
* @param string $form_name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param etemplate &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process($form_name,&$value,&$cell,&$readonlys,&$extension_data,$tmpl)
{
list($app) = explode('.',$tmpl->name);
// if we are in the etemplate editor or a different app, load the cf's from the app the tpl belongs to
if ($app && $app != 'stylite' && $app != $this->appname)
{
self::__construct(null,$app); // app changed
}
list($type2,$use_private,$field_names) = explode(',',$cell['size'],3);
$fields_with_vals=array();
// Filter fields
if($field_names)
{
if($field_names[0] == '!') {
$negate_field_filter = true;
$field_names = substr($field_names,1);
}
$field_filter = explode(',', $field_names);
}
$fields = $this->customfields;
foreach((array)$fields as $key => $field)
{
// remove private or non-private cf's, if only one kind should be displayed
if ((string)$use_private !== '' && (boolean)$field['private'] != (boolean)$use_private)
{
unset($fields[$key]);
}
// Remove filtered fields
if($field_filter && (!$negate_field_filter && !in_array($key, $field_filter) ||
$negate_field_filter && in_array($key, $field_filter)))
{
unset($fields[$key]);
}
}
// check if name refers to a single custom field --> show only that
if (($pos=@strpos($cell['name'],$this->prefix)) !== false && // allow the prefixed name to be an array index too
preg_match("/$this->prefix([^\]]+)/",$cell['name'],$matches) && isset($fields[$name=$matches[1]]))
{
$fields = array($name => $fields[$name]);
$value = array($this->prefix.$name => $value);
$singlefield = true;
$form_name = substr($form_name,0,-strlen("[$this->prefix$name]"));
}
switch($type = $cell['type'])
{
case 'customfields-types':
$cell['type'] = 'select';
foreach($this->cf_types as $lname => $label)
{
$cell['sel_options'][$lname] = lang($label);
$fields_with_vals[]=$lname;
}
$link_types = array_intersect(egw_link::app_list('query'),egw_link::app_list('title'));
ksort($link_types);
foreach($link_types as $lname => $label) $cell['sel_options'][$lname] = '- '.$label;
$cell['no_lang'] = true;
return true;
case 'customfields-list':
foreach(array_reverse($fields) as $lname => $field)
{
if (!empty($type2) && !empty($field['type2']) && strpos(','.$field['type2'].',',','.$type2.',') === false) continue; // not for our content type//
if (isset($value[$this->prefix.$lname]) && $value[$this->prefix.$lname] !== '') //break;
{
$fields_with_vals[]=$lname;
}
//$stop_at_field = $name;
}
break;
default:
foreach(array_reverse($fields) as $lname => $field)
{
$fields_with_vals[]=$lname;
}
}
$readonly = $cell['readonly'] || $readonlys[$name] || $type == 'customfields-list';
if(!is_array($fields))
{
$cell['type'] = 'label';
return True;
}
// making the cell an empty grid
$cell['type'] = 'grid';
$cell['data'] = array(array());
$cell['rows'] = $cell['cols'] = 0;
$cell['size'] = '';
$n = 1;
foreach($fields as $lname => $field)
{
if (array_search($lname,$fields_with_vals) !== false)
{
if ($stop_at_field && $lname == $stop_at_field) break; // no further row necessary
// check if the customfield get's displayed for type $value, we can have multiple comma-separated types now
if (!empty($type2) && !empty($field['type2']) && strpos(','.$field['type2'].',',','.$type2.',') === false)
{
continue; // not for our content type
}
$new_row = null; boetemplate::add_child($cell,$new_row);
if ($type != 'customfields-list' && $type == 'customfields')
{
$row_class = 'row';
boetemplate::add_child($cell,$label =& boetemplate::empty_cell('label','',array(
'label' => $field['label'],
'no_lang' => substr(lang($field['label']),-1) == '*' ? 2 : 0,
'span' => $field['type'] === 'label' ? '2' : '',
)));
}
elseif ($type == 'customfields-list')
{
if (isset($value[$this->prefix.$lname]) && $value[$this->prefix.$lname] !== '')
{
switch ((string)$field['type'])
{
case 'checkbox':
if ($value[$this->prefix.$lname]==0) break;
default:
boetemplate::add_child($cell,$input =& boetemplate::empty_cell('image','info.png',
array('label'=> $field['label'],'width'=>"16px")));
}
}
}
switch ((string)$field['type'])
{
case 'select' :
if (count($field['values']) == 1 && isset($field['values']['@']))
{
$field['values'] = egw_customfields::get_options_from_file($field['values']['@']);
}
if($this->advanced_search && $field['rows'] <= 1) $field['values'][''] = lang('doesn\'t matter');
foreach($field['values'] as $key => $val)
{
if (substr($val = lang($val),-1) != '*')
{
$field['values'][$key] = $val;
}
}
$input =& boetemplate::empty_cell('select',$this->prefix.$lname,array(
'sel_options' => $field['values'],
'size' => $field['rows'],
'enhance' => $field['enhance'],
'no_lang' => True,
));
if($this->advanced_search)
{
$select =& $input; unset($input);
$input =& boetemplate::empty_cell('hbox');
boetemplate::add_child($input, $select); unset($select);
/* the following seem to double the select fields in advanced search.
boetemplate::add_child($input, boetemplate::empty_cell('select',$this->prefix.$lname,array(
'sel_options' => $field['values'],
'size' => $field['rows'],
'no_lang' => True
)));
*/
}
break;
case 'ajax_select' :
// Set some reasonable defaults for the widget
$options = array(
'get_title' => 'etemplate.ajax_select_widget.array_title',
'get_rows' => 'etemplate.ajax_select_widget.array_rows',
'id_field' => ajax_select_widget::ARRAY_KEY,
);
if($field['rows']) {
$options['num_rows'] = $field['rows'];
}
// If you specify an option known to the AJAX Select widget, it will be pulled from the list of values
// and used as such. All unknown values will be used for selection, not passed through to the query
if (isset($field['values']['@']))
{
$options['values'] = $this->_get_options_from_file($field['values']['@']);
unset($field['values']['@']);
} else {
$options['values'] = array_diff_key($field['values'], array_flip(ajax_select_widget::$known_options));
}
$options = array_merge($options, array_intersect_key($field['values'], array_flip(ajax_select_widget::$known_options)));
$input =& boetemplate::empty_cell('ajax_select', $this->prefix.$lname, array(
'readonly' => $readonly,
'no_lang' => True,
'size' => $options
));
break;
case 'label' :
$row_class = 'th';
break;
case 'radio' :
$showthis = '#a#l#l#';
if (count($field['values']) == 1 && isset($field['values']['@']))
{
$field['values'] = $this->_get_options_from_file($field['values']['@']);
}
if($this->advanced_search && $field['rows'] <= 1) $field['values'][''] = lang('doesn\'t matter');
if ($readonly)
{
$showthis = $value[$this->prefix.$lname];
$input =& boetemplate::empty_cell('hbox');
}
else
{
$input =& boetemplate::empty_cell('groupbox');
}
$m = 0;
foreach ($field['values'] as $key => $val)
{
$radio = boetemplate::empty_cell('radio',$this->prefix.$lname);
$radio['label'] = $val;
$radio['size'] = $key;
if ($showthis == '#a#l#l#' || $showthis == $key) boetemplate::add_child($input,$radio);
unset($radio);
}
break;
case 'float':
case 'int':
$known_options = array('min'=>null, 'max'=>null,'size' => $field['len'], 'precision' => null);
$options = array_merge($known_options, $field['values']);
$input =& boetemplate::empty_cell($field['type'],$this->prefix.$lname,array(
'size' => implode(',',$options)
));
break;
case 'text' :
case 'textarea' :
case '' : // not set
$field['len'] = $field['len'] ? $field['len'] : 20;
if ($type != 'customfields-list')
{
if($field['rows'] <= 1)
{//text
list($max,$shown) = explode(',',$field['len']);
$tmparray=array(
'size' => intval($shown > 0 ? $shown : $max).','.intval($max),
'maxlength'=>intval($max),
'no_lang' => True,
);
if (is_array($field['values']))
{
if (array_key_exists('readonly',$field['values']))
{
if(!$this->advanced_search) $tmparray['readonly']='readonly';
}
}
$input =& boetemplate::empty_cell('text',$this->prefix.$lname,$tmparray);
}
else
{//textarea
$tmparray=array(
'size' => $field['rows'].($field['len'] >0 ? ','.(int)$field['len'] : ''),
'no_lang' => True,
);
if (is_array($field['values']) && array_key_exists('readonly',$field['values']))
{
if(!$this->advanced_search) $tmparray['readonly']='readonly';
}
$input =& boetemplate::empty_cell('textarea',$this->prefix.$lname,$tmparray);
}
}
else
{
$input =& boetemplate::empty_cell('label',$this->prefix.$lname,array('no_lang' => True));
}
break;
case 'date':
case 'date-time':
$input =& boetemplate::empty_cell($field['type'],$this->prefix.$lname,array(
'size' => $field['len'] ? $field['len'] : ($field['type'] == 'date' ? 'Y-m-d' : 'Y-m-d H:i:s'),
));
break;
case 'select-account':
list($opts) = explode('=',$field['values'][0]);
$input =& boetemplate::empty_cell('select-account',$this->prefix.$lname,array(
'size' => ($field['rows']>1?$field['rows']:lang('None')).','.$opts,
));
break;
case 'button': // button(s) to execute javascript (label=onclick) or textinputs (empty label, readonly with neg. length)
// a button does not seem to be helpful in advanced search ???,
if($this->advanced_search) break;
$input =& boetemplate::empty_cell('hbox');
foreach($field['values'] as $label => $js)
{
if (!$label) // display an readonly input
{
$tmparray = array(
'size' => $field['len'] ? $field['len'] : 20,
'readonly' => $field['len'] < 0,
'onchange' => $js,
);
$widget =& boetemplate::empty_cell('text',$this->prefix.$lname.$label,$tmparray);
}
else
{
if ($readonly) continue; // dont display buttons if we're readonly
$widget =& boetemplate::empty_cell('buttononly',$this->prefix.$lname.$label,array(
'label' => $label ? $label : lang('Submit'),
'onclick' => $js,
'no_lang' => True
));
}
boetemplate::add_child($input,$widget);
unset($widget);
}
break;
case 'url-email':
list($max,$shown,$validation_type,$default) = explode(',',$field['len'],4);
if (empty($max)) $max =128;
if (empty($shown)) $shown = 28;
if (empty($validation_type)) $validation_type = 1;
$field['len'] = implode(',',array($shown, $max, $validation_type, $default));
$input =& boetemplate::empty_cell($field['type'],$this->prefix.$lname,array(
'size' => $field['len']
));
break;
case 'url':
case 'url-phone':
list($max,$shown,$validation_type) = explode(',',$field['len'],3);
if (empty($max)) $max =128;
if (empty($shown)) $shown = 28;
$field['len']=implode(',',array( $shown, $max, $validation_type));
$input =& boetemplate::empty_cell($field['type'],$this->prefix.$lname,array(
'size' => $field['len']
));
break;
case 'htmlarea': // defaults: len: width=100%,mode=simple,tooldbar=false; rows: 5
list($width,$mode,$toolbar) = explode(',',$field['len']);
$input =& boetemplate::empty_cell($field['type'],$this->prefix.$lname,array(
'size' => $mode.','.(($field['rows'] ? $field['rows'] : 5)*16).'px,'.$width.','.($toolbar=='true'?'true':'false'),
));
break;
// other etemplate types, which are used just as is
case 'checkbox' :
$input =& boetemplate::empty_cell($field['type'],$this->prefix.$lname);
break;
case 'link-entry':
default : // link-entry to given app
$input =& boetemplate::empty_cell('link-entry',$this->prefix.$lname,array(
'size' => $field['type'] == 'link-entry' ? '' : $field['type'],
));
// register post-processing of link widget to get eg. needed/required validation
etemplate::$request->set_to_process(etemplate::form_name($form_name,$this->prefix.$lname), 'ext-link');
}
$cell['data'][0]['c'.$n++] = $row_class.',top';
if (!is_null($input))
{
if ($readonly) $input['readonly'] = true;
$input['needed'] = $cell['needed'] || $field['needed'];
if (!empty($field['help']) && $row_class != 'th')
{
$input['help'] = $field['help'];
$input['no_lang'] = substr(lang($help),-1) == '*' ? 2 : 0;
}
if ($singlefield) // a single field, can & need to be returned instead of the cell (no grid)
{
$input['span'] = $cell['span']; // set span & class from original cell
$cell = $input;
if ($type == 'customfields') $cell['label'] = $field['label'];
$value = $value[$this->prefix.$lname];
return true;
}
boetemplate::add_child($cell,$input);
unset($input);
}
unset($label);
}
}
if ($type != 'customfields-list')
{
$cell['data'][0]['A'] = '100';
}
list($span,$class) = explode(',',$cell['span']); // msie (at least 5.5) shows nothing with div overflow=auto
// we dont want to use up the full space for the table created, so we skip the line below
//$cell['size'] = '100%,100%,0,'.$class.','.(in_array($type,array('customfields-list','customfields-no-label'))?'0,0':',').(html::$user_agent != 'msie' ? ',auto' : '');
return True; // extra Label is ok
}
/**
* Check if there are links in the custom fields and update them
*
* This function have to be called manually by an application, if cf's linking
* to other entries should be stored as links too (beside as cf's).
*
* @param string $own_app own appname
* @param array $values new values including the custom fields
* @param array $old =null old values before the update, if existing
* @param string $id_name ='id' name/key of the (link-)id in $values
* @deprecated use egw_customfields::update_links($own_app,array $values,array $old=null,$id_name='id')
*/
public static function update_customfield_links($own_app,array $values,array $old=null,$id_name='id')
{
return egw_customfields::update_links($own_app, $values, $old , $id_name);
}
/**
* Format a single custom field value as string
*
* @param array $field field defintion incl. type
* @param string $value field value
* @return string formatted value
* @deprecated use egw_customfields::format($field, $value)
*/
public static function format_customfield(array $field, $value)
{
return egw_customfields::format($field, $value);
}
}

View File

@ -1,676 +0,0 @@
<?php
/**
* eGroupWare eTemplate Extension - Date Widget
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @copyright 2002-9 by RalfBecker@outdoor-training.de
* @package etemplate
* @subpackage extensions
* @version $Id$
*/
/**
* eTemplate extension to input or display date and/or time values
*
* Contains the following widgets: Date, Date+Time, Time, Hour, Duration
*
* Supported attributes: format[,options]
* format: '' = timestamps or automatic conversation, or eg. 'Y-m-d H:i:s' for 2002-12-31 23:59:59
* options: &1 = year is int-input not selectbox, &2 = show a [Today] button, (html-UI always uses jscal and dont care for &1+&2)
* &4 = 1min steps for time (default is 5min, with fallback to 1min if value is not in 5min-steps),
* &8 = dont show time for readonly and type date-time if time is 0:00,
* &16 = prefix r/o display with dow
* &32 = prefix r/o display with week-number
* &64 = prefix r/o display with weeknumber and dow
* &128 = no icon to trigger popup, click into input trigers it, also removing the separators to save space
* This widget is independent of the UI as it only uses etemplate-widgets and has therefor no render-function.
* Uses the adodb datelibary to overcome the windows-limitation to not allow dates before 1970
*/
class date_widget
{
/**
* exported methods of this class
* @var array
*/
var $public_functions = array(
'pre_process' => True,
'post_process' => True
);
/**
* available extensions and there names for the editor
* @var array
*/
var $human_name = array(
'date' => 'Date', // just a date, no time
'date-time' => 'Date+Time', // date + time
'date-timeonly' => 'Time', // time
'date-houronly' => 'Hour', // hour
'date-duration' => 'Duration', // duration
'date-since' => 'Time since', // time past since given time
'date-time_today' => 'Date or todays time',
);
var $dateformat; // eg. Y-m-d, d-M-Y
var $timeformat; // 12 or 24
/**
* Reference to global jscalencar object
*
* @var jscalendar
*/
var $jscal;
/**
* Constructor of the extension
*
* @param string $ui '' for html
*/
function __construct($ui)
{
if ($ui == 'html')
{
$this->jscal = $GLOBALS['egw']->jscalendar;
}
$this->timeformat = $GLOBALS['egw_info']['user']['preferences']['common']['timeformat'];
$this->dateformat = $GLOBALS['egw_info']['user']['preferences']['common']['dateformat'];
}
/**
* pre-processing of the extension
*
* This function is called before the extension gets rendered
*
* @param string $name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param object &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process($name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl)
{
//echo "<p>".__METHOD__."($name,$value=".egw_time::to($value).",".array2string($cell).")</p>\n";
$type = $cell['type'];
switch ($type)
{
case 'date-duration':
return $this->pre_process_duration($name,$value,$cell,$readonlys,$extension_data,$tmpl);
}
list($data_format,$options,$options2) = explode(',',$cell['size']);
if ($type == 'date-houronly' && empty($data_format)) $data_format = 'H';
$readonly = $cell['readonly'] || $readonlys || $type == 'date-since';
if (!$readonly) // dont set extension-data on readonly, it's not needed and can conflict with other widgets
{
$extension_data = array(
'type' => $type,
'data_format' => $data_format,
);
}
// automatic convert db timestamps to unix timestamps, our db class does the reverse on writing them
if ($value && !$data_format && !is_numeric($value) && ($v = strtotime($value)))
{
$value = $value === '0000-00-00 00:00:00' ? null : $v;
}
// for date-(time|hour)only widgets we distinct between between 0 and ''/null timestamps
if (!$value && ($type != 'date-timeonly' && $type != 'date-houronly' || (string)$value === ''))
{
$value = array(
'Y' => '',
'm' => '',
'd' => '',
'H' => '',
'i' => '',
);
}
elseif (!is_object($value) && $data_format != '') // we ignore format for objects
{
$date = preg_split('/[- \\/.:,]/',$value);
//echo "date=<pre>"; print_r($date); echo "</pre>";
$mdy = preg_split('/[- \\/.:,]/',$data_format);
if (count($mdy) == 1) // no seperators, eg. YmdHi
{
for($n = $i = 0; $n < strlen($data_format); ++$n)
{
$mdy[$n] = $data_format[$n];
$len = $data_format[$n] == 'Y' ? 4 : 2;
$date[$n] = substr($value,$i,$len);
$i += $len;
}
}
$value = array();
foreach ($date as $n => $dat)
{
switch($mdy[$n])
{
case 'Y': $value['Y'] = (int) $dat; break;
case 'm': $value['m'] = (int) $dat; break;
case 'd': $value['d'] = (int) $dat; break;
case 'H': $value['H'] = (int) $dat; break;
case 'i': $value['i'] = (int) $dat; break;
}
}
}
else
{
// for the timeformats we use only seconds, no timezone conversation between server-time and UTC
if (substr($type,-4) == 'only' && is_numeric($value)) $value -= adodb_date('Z',0);
$value = egw_time::to($value,'date_array');
}
if ($type == 'date-since')
{
return $this->pre_process_since($value,$cell);
}
$time_0h0 = !(int)$value['H'] && !(int)$value['i'];
$timeformat = array(3 => 'H', 4 => 'i');
if ($this->timeformat == '12' && $readonly && $value['H'] !== '')
{
$value['a'] = $value['H'] < 12 ? 'am' : 'pm';
$value['H'] = $value['H'] % 12 ? $value['H'] % 12 : 12; // no leading 0 and 0h => 12am
$timeformat += array(5 => 'a');
}
$format = preg_split('/[\\/.-]/',$this->dateformat);
// no time also if $options&8 and readonly and time=0h0
if ($type != 'date' && !($readonly && ($options & 8) && $time_0h0))
{
$format += $timeformat;
}
if ($value['m'] && strchr($this->dateformat,'M') !== false)
{
static $month = array('','January','February','March','April','May','June','July','August','September','October','November','December');
static $substr;
if (is_null($substr)) $substr = function_exists('mb_substr') ? 'mb_substr' : 'substr';
static $chars_shortcut;
if (is_null($chars_shortcut)) $chars_shortcut = (int)lang('3 number of chars for month-shortcut'); // < 0 to take the chars from the end
$value['M'] = lang($m = substr($month[$value['m']],0,3)); // check if we have a translation of the short-cut
if ($value['M'] == $m || $substr($value['M'],-1) == '*') // if not generate one by truncating the translation of the long name
{
$value['M'] = $chars_shortcut > 0 ? $substr(lang($month[$value['m']]),0,$chars_shortcut) :
$substr(lang($month[$value['m']]),$chars_shortcut);
}
}
if ($readonly) // is readonly
{
if ($type == 'date-time_today')
{
$today = new egw_time();
if ($value['Y'].$value['d'].$value['m'] == $today->format('Ymd'))
{
$format = $timeformat;
}
else
{
$format = $dateformat;
}
}
if ($value['H'] === '') unset($value['a']); // no am/pm if no hour set
$sep = array(
1 => $this->dateformat[1],
2 => $this->dateformat[1],
3 => ' ',
4 => ':'
);
for ($str='',$n = substr($type,-4) == 'only' ? 3 : 0; $n < count($format); ++$n)
{
if ($value[$format[$n]] && $n < 3 || $n >= 3 && ($value[$format[3]] !== '' || $value[$format[4]] !== ''))
{
if (!$n && $options & 16 )
{
$str = lang(adodb_date('l',adodb_mktime(12,0,0,$value['m'],$value['d'],$value['Y']))).' ';
}
if (!$n && $options & 32 )
{
$str = lang('Wk').adodb_date('W',adodb_mktime(12,0,0,$value['m'],$value['d'],$value['Y'])).' ';
}
if (!$n && $options & 64 )
{
$str = lang('Wk').adodb_date('W',adodb_mktime(12,0,0,$value['m'],$value['d'],$value['Y'])).' '.lang(adodb_date('l',adodb_mktime(12,0,0,$value['m'],$value['d'],$value['Y']))).' ';
}
$str .= ($str != '' ? $sep[$n] : '') .
(is_numeric($value[$format[$n]]) ? sprintf('%02d',$value[$format[$n]]) : $value[$format[$n]]);
}
if ($type == 'date-houronly') ++$n; // no minutes
}
$value = $str;
$cell['type'] = 'label';
if (!$cell['no_lang'])
{
$cell['no_lang'] = True;
$cell['label'] = strlen($cell['label']) > 1 ? lang($cell['label']) : $cell['label'];
}
unset($cell['size']);
return True;
}
if ($type == 'date-time_today') $type = 'date-time'; // no special handling for input
if ($cell['needed'])
{
etemplate::$request->set_to_process($name,'ext-'.$type,array(
'needed' => $cell['needed'],
));
}
$tpl = new etemplate;
$tpl->init('*** generated fields for date','','',0,'',0,0); // make an empty template
// keep the editor away from the generated tmpls
$tpl->no_onclick = true;
$types = array(
'Y' => ($options&1 ? 'int' : 'select-year'), // if options&1 set, show an int-field
'm' => 'select-month',
'M' => 'select-month',
'd' => 'select-day',
'H' => 'select-hour',
'i' => 'select-number'
);
$opts = array(
'H' => $this->timeformat == '12' ? ',0,12' : ',0,23,01',
'i' => $value['i'] % 5 || $options & 4 ? ',0,59,01' : ',0,59,05' // 5min steps, if ok with value
);
$help = array(
'Y' => 'Year',
'm' => 'Month',
'M' => 'Month',
'd' => 'Day',
'H' => 'Hour',
'i' => 'Minute'
);
$row = array();
for ($i=0,$n= substr($type,-4) == 'only' ? 3 : 0; $n < ($type == 'date' ? 3 : 5); ++$n,++$i)
{
$dcell = $tpl->empty_cell();
if ($cell['tabindex']) $dcell['tabindex'] = $cell['tabindex'];
if (!$i && $cell['accesskey']) $dcell['accesskey'] = $cell['accesskey'];
// test if we can use jsCalendar
if ($n == 0 && $this->jscal)
{
$dcell['type'] = 'html';
$dcell['name'] = 'str';
$cname_parts = array_splice(explode('[',str_replace(']','',$name)), 0, -count(explode('[',str_replace(']','',$cell['name']))));
$cname = array_shift($cname_parts);
if ($cname_parts) $cname .= '['.implode('][', $cname_parts).']';
$jscaloptions = $cell['onchange'] ? ( ' onchange="'. ( (int)$cell['onchange'] === 1 ? 'this.form.submit();"' : $tmpl->js_pseudo_funcs($cell['onchange'],$cname). '"' ) ) : '' ;
$value['str'] = $this->jscal->input($name.'[str]',False,$value['Y'],$value['m'],$value['d'],lang($cell['help']),$jscaloptions,false,!($options & 128));
$n = 2; // no other fields
$options &= ~2; // no set-today button
}
else
{
$dcell['type'] = $types[$format[$n]];
$dcell['size'] = $opts[$format[$n]];
$dcell['name'] = $format[$n];
$dcell['help'] = lang($help[$format[$n]]).': '.lang($cell['help']); // note: no lang on help, already done
}
if ($n == 4)
{
$dcell['label'] = $options & 128 ? '' : ':'; // put a : between hour and minute
}
$dcell['no_lang'] = 2;
$row[$tpl->num2chrs($i)] = &$dcell;
unset($dcell);
if ($n == 2 && ($options & 2)) // Today button
{
$dcell = $tpl->empty_cell();
if ($cell['tabindex']) $dcell['tabindex'] = $cell['tabindex'];
$dcell['name'] = 'today';
$dcell['label'] = 'Today';
$dcell['help'] = 'sets today as date';
$dcell['no_lang'] = True;
$dcell['needed'] = True; // to get a button
$dcell['onchange'] = "this.form.elements['$name"."[Y]'].value='".adodb_date('Y')."'; this.form.elements['$name"."[m]'].value='".adodb_date('n')."';this.form.elements['$name"."[d]'].value='".(0+adodb_date('d'))."'; return false;";
$dcell['type'] = 'button';
$row[$tpl->num2chrs(++$i)] = &$dcell;
unset($dcell);
}
if ($n == 2 && $type == 'date-time' && !($options & 128)) // insert some space between date+time
{
$dcell = $tpl->empty_cell();
$dcell['type'] = 'html';
$dcell['name'] = 'space';
$value['space'] = ' &nbsp; &nbsp; ';
$row[$tpl->num2chrs(++$i)] = &$dcell;
unset($dcell);
}
if ($type == 'date-houronly') $n++; // no minutes
}
$tpl->data[0] = array();
$tpl->data[1] = &$row;
$tpl->set_rows_cols();
$tpl->size = ',,,,0';
$cell['size'] = $cell['name'];
$cell['type'] = 'template';
$cell['name'] = $tpl->name;
$cell['obj'] = &$tpl;
$cell['span'] .= (strpos($cell['span'],',')===false?',':'').($cell['span']?' ':'').'eTdate';
return True; // extra Label is ok
}
/**
* pre-processing of the duration extension
*
* Options contain $data_format,$input_format,$hours_per_day,$empty_not_0,$short_labels
* 1. data_format: d = days, h = hours, m = minutes, default minutes
* 2. input_format: d = days, h = hours, m = minutes, default hours+days (selectbox), optional % = allow to enter a percent value (no conversation)
* 3. hours_per_day: default 8 (workday)
* 4. should the widget differ between 0 and empty, which get then returned as NULL
* 5. short_labels use d/h/m instead of day/hour/minute
*
* @param string $name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param object &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process_duration($name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl)
{
//echo "<p>pre_process_duration($name,$value,...) cell[size]='$cell[size]'</p>\n";
$readonly = $readonlys || $cell['readonly'];
list($data_format,$input_format,$hours_per_day,$empty_not_0,$short_labels) = explode(',',$cell['size']);
if (!$hours_per_day) $hours_per_day = 8; // workday is 8 hours
if (($percent_allowed = strpos($input_format,'%') !== false))
{
$input_format = str_replace('%','',$input_format);
}
if (!in_array($input_format,array('d','h','dh','m','hm','dhm'))) $input_format = 'dh'; // hours + days
$unit = $input_format == 'd' ? 'd' : 'h';
if (!$readonly) // dont set extension-data on readonly, it's not needed and can conflict with other widgets
{
$extension_data = array(
'type' => $cell['type'],
'data_format' => $data_format,
'unit' => $unit,
'input_format' => $input_format,
'hours_per_day' => $hours_per_day,
'percent_allowed'=> $percent_allowed,
'empty_not_0' => $empty_not_0,
);
$cell['size'] = '4,,/^-?[0-9]*[,.]?[0-9]*'.($percent_allowed ? '%?' : '').'$/';
}
if ($value)
{
switch($data_format)
{
case 'd':
$value *= $hours_per_day;
// fall-through
case 'h': case 'H':
$value *= 60;
break;
}
}
$cell['type'] = 'text';
$cell_name = $cell['name'];
$cell['name'] .= '[value]';
if (strpos($input_format,'m') !== false && $value && $value < 60)
{
$unit = 'm';
}
elseif (strpos($input_format,'d') !== false && $value >= 60*$hours_per_day)
{
$unit = 'd';
}
$value = $empty_not_0 && (string) $value === '' || !$empty_not_0 && !$value ? '' :
($unit == 'm' ? (int) $value : round($value / 60 / ($unit == 'd' ? $hours_per_day : 1),3));
// use decimal separator from user prefs
if (($sep = $GLOBALS['egw_info']['user']['preferences']['common']['number_format'][0]) && $sep != '.')
{
$value = str_replace('.',$sep,$value);
}
if (!$readonly && strlen($input_format) > 1) // selectbox to switch between hours and days
{
$value = array(
'value' => $value,
'unit' => $unit,
);
$tpl = new etemplate;
$tpl->init('*** generated fields for duration','','',0,'',0,0); // make an empty template
// keep the editor away from the generated tmpls
$tpl->no_onclick = true;
$selbox =& $tpl->empty_cell('select',$cell_name.'[unit]');
if (strpos($input_format,'m') !== false) $selbox['sel_options']['m'] = $short_labels ? 'm' : 'minutes';
if (strpos($input_format,'h') !== false) $selbox['sel_options']['h'] = $short_labels ? 'h' : 'hours';
if (strpos($input_format,'d') !== false) $selbox['sel_options']['d'] = $short_labels ? 'd' : 'days';
if ($cell['tabindex']) $selbox['tabindex'] = $cell['tabindex'];
$tpl->data[0] = array();
$tpl->data[1] =array(
'A' => $cell,
'B' => $selbox,
);
$tpl->set_rows_cols();
$tpl->size = ',,,,0';
unset($cell['size']);
$cell['type'] = 'template';
$cell['name'] = $tpl->name;
unset($cell['label']);
$cell['obj'] = &$tpl;
}
elseif (!$readonly || $value)
{
$cell['no_lang'] = 2;
$cell['label'] .= ($cell['label'] ? ' ' : '') . '%s ';
switch($unit)
{
case 'm': $cell['label'] .= $short_labels ? 'm' : lang('minutes'); break;
case 'h': $cell['label'] .= $short_labels ? 'h' : lang('hours'); break;
case 'd': $cell['label'] .= $short_labels ? 'd' : lang('days'); break;
}
}
return True; // extra Label is ok
}
/**
* pre-processing of the time since extension
*
* @param array &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process_since(&$value,&$cell)
{
static $unit2label = array(
'Y' => 'years',
'm' => 'month',
'd' => 'days',
'H' => 'hours',
'i' => 'minutes',
's' => 'seconds',
);
static $unit2s = array(
'Y' => 31536000,
'm' => 2628000,
'd' => 86400,
'H' => 3600,
'i' => 60,
's' => 1,
);
$cell = boetemplate::empty_cell('label','',array('label'=>$cell['label']));
if ((string)$value['Y'] !== '')
{
if (!is_object($GLOBALS['egw']->datetime))
{
$GLOBALS['egw']->datetime = new egw_datetime();
}
$now_s = time() + $GLOBALS['egw']->datetime->tz_offset; // time() is server-time and we need a user-time
$val_s = mktime($value['H'],$value['i'],$value['s'],$value['m'],$value['d'],$value['Y']);
$diff_s = $now_s - $val_s;
foreach($unit2s as $unit => $unit_s)
{
if ($diff_s >= $unit_s || $unit == 's')
{
$value = round($diff_s/$unit_s,1).' '.lang($unit2label[$unit]);
break;
}
//echo "<p>$unit: diff_s=$diff_s >= $unit_s --> continue</p>\n";
}
}
else
{
$value = '';
}
return true;
}
/**
* postprocessing method, called after the submission of the form
*
* It has to copy the allowed/valid data from $value_in to $value, otherwise the widget
* will return no data (if it has a preprocessing method). The framework insures that
* the post-processing of all contained widget has been done before.
*
* Only used by select-dow so far
*
* @param string $name form-name of the widget
* @param mixed &$value the extension returns here it's input, if there's any
* @param mixed &$extension_data persistent storage between calls or pre- and post-process
* @param boolean &$loop can be set to true to request a re-submision of the form/dialog
* @param object &$tmpl the eTemplate the widget belongs too
* @param mixed &value_in the posted values (already striped of magic-quotes)
* @return boolean true if $value has valid content, on false no content will be returned!
*/
function post_process($name,&$value,&$extension_data,&$loop,&$tmpl,$value_in)
{
//echo "<p>date_widget::post_process('$name','$extension_data[type]','$extension_data[data_format]') value="; print_r($value); echo ", value_in="; print_r($value_in); echo "</p>\n";
if (!isset($value) && !isset($value_in))
{
return False;
}
if ($extension_data['type'] == 'date-duration')
{
if (is_array($value)) // template with selectbox
{
$unit = $value['unit'];
$value = $value['value'];
}
elseif (!preg_match('/^-?[0-9]*[,.]?[0-9]*'.($extension_data['percent_allowed'] ? '%?' : '').'$/',$value_in))
{
etemplate::set_validation_error($name,lang("'%1' is not a valid floatingpoint number !!!",$value_in));
return false;
}
else
{
$value = $value_in;
$unit = $extension_data['unit'];
}
if ($extension_data['percent_allowed'] && substr($value,-1) == '%')
{
return true;
}
if ($value === '' && $extension_data['empty_not_0']) // we differ between 0 and empty, which get returned as null
{
$value = null;
return true;
}
$value = (int) round(str_replace(',','.',$value) * ($unit == 'm' ? 1 : (60 * ($unit == 'd' ? $extension_data['hours_per_day'] : 1))));
switch($extension_data['data_format'])
{
case 'd':
$value /= (float) $extension_data['hours_per_day'];
// fall-through
case 'h': case 'H':
$value /= 60.0;
break;
}
return true;
}
$no_date = substr($extension_data['type'],-4) == 'only';
if ($value['today'])
{
$set = array('Y','m','d');
foreach($set as $d)
{
$value[$d] = adodb_date($d);
}
}
if (isset($value_in['str']) && !empty($value_in['str']))
{
if (!is_array($value))
{
$value = array();
}
$value += $this->jscal->input2date($value_in['str'],False,'d','m','Y');
}
if ($value['d'] || $no_date &&
(isset($value['H']) && $value['H'] !== '' || isset($value['i']) && $value['i'] !== ''))
{
if ($value['d'])
{
if (!$value['m'])
{
$value['m'] = adodb_date('m');
}
if (!$value['Y'])
{
$value['Y'] = adodb_date('Y');
}
elseif ($value['Y'] < 100)
{
$value['Y'] += $value['Y'] < 30 ? 2000 : 1900;
}
}
else // for the timeonly field
{
$value['d'] = $value['m'] = 1;
$value['Y'] = 1970;
}
// checking the date is a correct one
if (!checkdate($value['m'],$value['d'],$value['Y']))
{
etemplate::set_validation_error($name,lang("'%1' is not a valid date !!!",
common::dateformatorder($value['Y'],$value['m'],$value['d'],true)));
}
$data_format = $extension_data['data_format'];
if (empty($data_format))
{
// for time or hour format we use just seconds (and no timezone correction between server-time and UTC)
$value = $no_date ? 3600 * (int) $value['H'] + 60 * (int) $value['i'] :
adodb_mktime((int) $value['H'],(int) $value['i'],0,$value['m'],$value['d'],$value['Y']);
}
else
{
for ($n = 0,$str = ''; $n < strlen($data_format); ++$n)
{
if (strpos('YmdHis',$c = $data_format[$n]) !== false)
{
$str .= sprintf($c=='Y'?'%04d':'%02d',$value[$c]);
}
else
{
$str .= $c;
}
}
$value = $str;
}
}
else
{
$value = '';
}
return True;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,27 +0,0 @@
<?php
/**
* EGroupware - eTemplate serverside
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage api
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @copyright 2002-16 by RalfBecker@outdoor-training.de
* @version $Id$
*/
use EGroupware\Api;
/**
* New eTemplate serverside contains:
* - main server methods like read, exec
* -
*
* Not longer available methods:
* - set_(row|column)_attributes modifies template on run-time, was only used internally by etemplate itself
* - disable_(row|column) dto.
*
* @deprecated use Api\Etemplate
*/
class etemplate_new extends Api\Etemplate {}

View File

@ -1,21 +0,0 @@
<?php
/**
* EGroupware - eTemplate request object
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage etemplate
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @copyright (c) 2007-16 by Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/
use EGroupware\Api\Etemplate\Request;
/**
* Class to represent the persitent information of an eTemplate request
*
* @deprecated use Api\Etemplate\Request
*/
class etemplate_request extends Request {}

View File

@ -1,14 +0,0 @@
<?php
class etemplate_table_test
{
var $public_functions = array(
'index' => true,
);
function index(array $content=null, $msg='')
{
$tmpl = new etemplate_new('etemplate.table_test');
$content = array();
$tmpl->exec('etemplate.etemplate_table_test.index', $content);
}
}

View File

@ -1,74 +0,0 @@
<?php
/**
* EGroupware - eTemplate widget moved to EGroupware\Api\Etemplate\Widget
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage api
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @copyright 2002-16 by RalfBecker@outdoor-training.de
* @version $Id$
*/
use EGroupware\Api\Etemplate\Widget;
use EGroupware\Api\Etemplate;
/**
* eTemplate widget baseclass
*
* @deprecated use Api\Etemplate\Widget
*/
class etemplate_widget extends Etemplate\Widget {}
/**
* eTemplate Extension: Entry widget
*
* This widget can be used to fetch fields of any entry specified by its ID.
* The entry is loaded once and shared amoung widget that need it.
*
* @deprecated use Api\Etemplate\Widget\Entry
*/
abstract class etemplate_widget_entry extends Widget\Entry {}
/**
* eTemplate Select widget
*
* @deprecated use Api\Etemplate\Widget\Select
*/
class etemplate_widget_menupopup extends Widget\Select {}
/**
* eTemplate Link widgets
*
* @deprecated use Api\Etemplate\Widget\Link
*/
class etemplate_widget_link extends Widget\Link {}
/**
* eTemplate Nextmatch widgets
*
* @deprecated use Api\Etemplate\Widget\Nextmatch
*/
class etemplate_widget_nextmatch extends Widget\Nextmatch {}
/**
* eTemplate Taglist widgets
*
* @deprecated use Api\Etemplate\Widget\Taglist
*/
class etemplate_widget_taglist extends Widget\Taglist {}
/**
* eTemplate File widgets
*
* @deprecated use Api\Etemplate\Widget\File
*/
class etemplate_widget_file extends Widget\File {}
/**
* eTemplate Vfs widgets
*
* @deprecated use Api\Etemplate\Widget\Vfs
*/
class etemplate_widget_vfs extends Widget\Vfs {}

View File

@ -1,55 +0,0 @@
<?php
/**
* EGroupware - eTemplate serverside base widget, to define new widgets using a transformation out of existing widgets
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage api
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @copyright 2002-16 by RalfBecker@outdoor-training.de
* @version $Id$
*/
use EGroupware\Api\Etemplate\Widget\Transformer;
/**
* eTemplate serverside base widget, to define new widgets using a transformation out of existing widgets
*
* @deprecated use Api\Etemplate\Widget\Transformer
*/
abstract class etemplate_widget_transformer extends Transformer
{
/**
* Rendering transformer widget serverside as an old etemplate extension
*
* This function is called before the extension gets rendered
*
* @param string $name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param etemplate &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
public function pre_process($name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl)
{
unset($readonlys, $extension_data, $tmpl); // not used but required by function signature
$_value = $value;
$_cell = $cell;
$cell['value'] =& $value;
$cell['options'] =& $cell['size']; // old engine uses 'size' instead of 'options' for legacy options
$cell['id'] =& $cell['name']; // dto for 'name' instead of 'id'
// run the transformation
foreach(static::$transformation as $filter => $data)
{
$this->action($filter, $data, $cell);
}
unset($cell['value']);
error_log(__METHOD__."('$name', ".(is_array($_value)?$_value['id']:$_value).", ".array2string($_cell).", ...) transformed to ".array2string($cell)." and value=".array2string($value));
return true;
}
}

View File

@ -1,21 +0,0 @@
<?php
/**
* EGroupware - eTemplate widget moved to EGroupware\Api\Etemplate\Widget
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage api
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @copyright 2002-16 by RalfBecker@outdoor-training.de
* @version $Id$
*/
use EGroupware\Api\Etemplate\Widget\Tree;
/**
* eTemplate Tree widget
*
* @deprecated use Api\Etemplate\Widget\Tree
*/
class etemplate_widget_tree extends Tree {}

View File

@ -1,283 +0,0 @@
<?php
/**
* eTemplate Widget for the historylog
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @link http://www.egroupware.org
* @author RalfBecker-At-outdoor-training.de
* @copyright 2006-11 by RalfBecker-At-outdoor-training.de
* @license GPL - GNU General Public License
* @version $Id$
*/
/**
* This widget shows the historylog for one entry of an application
*
* It takes as parameter either just the id or an array with the following keys:
* - 'id' integer id of the entry
* - 'app' string app-name, defaults to $GLOBALS['egw_info']['flags']['currentapp']
* - 'status-widgets' array with status-values as key and widget names or array with select-options as value,
* all not set stati are displayed via a label-widget - just as text
* widget types for custom fields do NOT need to be added, they are automatically detected!
* You can set $sel_options['status'] to translate the status-values to meaningful labels.
* If status is already used for a field, you can also set options to an other name, eg. 'labels' or 'fields'
*
* If you have a 1:N relation the 'status-widget' entry should be an array with widget types as values (corresponding
* to order and fields used in bo_tracking's field2history array).
*
* @package etemplate
* @subpackage extensions
* @author RalfBecker-At-outdoor-training.de
*/
class historylog_widget
{
/**
* Maximum number of log entries to display
*/
const MAX_DISPLAY = 500;
/**
* @var array exported methods of this class
*/
var $public_functions = array(
'pre_process' => True,
);
/**
* @var array/string availible extensions and there names for the editor
*/
var $human_name = array(
'historylog' => 'History Log',
// 'historylog-helper' => '',
);
static $status_widgets;
/**
* pre-processing of the historylog-helper
*
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @return boolean true if extra label is allowed, false otherwise
*/
private function pre_process_helper(&$value, &$cell, $tmpl)
{
if (empty($value) && (string)$value !== '0')
{
$cell = boetemplate::empty_cell();
return true;
}
//echo $value.'/'.$cell['size']; _debug_array(self::$status_widgets);
$type = isset(self::$status_widgets[$cell['size']]) ? self::$status_widgets[$cell['size']] : 'label';
$options = '';
if (!is_array($type) && strpos($type,':') !== false)
{
list($type,$options) = explode(':',$type,2);
}
// For all select-cats, show missing entries as IDs
if($type == 'select-cat')
{
list($rows,$type1,$type2,$type3,$type4,$type5,$type6) = explode(',',$options);
$type6 = 2;
$options = implode(',',array($rows,$type1,$type2,$type3,$type4,$type5,$type6));
}
$cell = boetemplate::empty_cell($type,$cell['name'],array('readonly' => true,'size' => $options));
// display unsupported iCal properties, which have multiple values or attributes, or multiple components
if ($type === 'label' && $value[1] === ':' && ($values = unserialize($value)))
{
if (isset($values['values']))
{
foreach((array)$values['params'] as $name => $val)
{
$values['values'][] = $name.': '.$val;
}
$values = $values['values'];
}
$value = implode("\n", $values);
}
elseif (is_array($type))
{
list($t) = explode(':',$type[0]);
if (isset($type[0]) && // numeric indexed array --> multiple values of 1:N releation
$tmpl->widgetExists($t))
{
$cell['type'] = 'vbox';
$cell['size'] = '0,,0,0';
$value = explode(bo_tracking::ONE2N_SEPERATOR,$value);
foreach($type as $n => $t)
{
$opt = '';
if(is_array($t))
{
$sel_options = $t;
$t = 'select';
}
else
{
list($t,$opt) = explode(':',$t);
}
$child = boetemplate::empty_cell($t,$cell['name']."[$n]",array('readonly' => true,'no_lang' => true,'size' => $opt));
$child['sel_options'] = $sel_options;
boetemplate::add_child($cell,$child);
unset($sel_options);
unset($child);
}
}
else
{
$cell['sel_options'] = $cell['type'];
$cell['type'] = 'select';
}
}
// For all times, show time in user time
elseif ($type == 'date-time' && $value)
{
$value = egw_time::server2user($value);
}
if ($cell['type'] == 'label') $cell['no_lang'] = 'true';
return true;
}
/**
* pre-processing of the history logging extension
*
* @param string $name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param etemplate $tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process($name,&$value,&$cell,&$readonlys,&$extension_data,$tmpl)
{
switch ($cell['type'])
{
case 'historylog-helper':
return $this->pre_process_helper($value, $cell, $tmpl);
}
$app = is_array($value) ? $value['app'] : $GLOBALS['egw_info']['flags']['currentapp'];
self::$status_widgets = is_array($value) && isset($value['status-widgets']) ? $value['status-widgets'] : null;
$id = is_array($value) ? $value['id'] : $value;
$filter = is_array($value) ? $value['filter'] : array();
$historylog = new historylog($app);
if (!$id || method_exists($historylog,'search'))
{
$value = $id ? $historylog->search($filter ? array('history_record_id'=>$id) + $filter : $id, 'history_id', 'DESC', self::MAX_DISPLAY) : false;
}
unset($historylog);
$tpl = new etemplate;
$tpl->init('*** generated fields for historylog','','',0,'',0,0); // make an empty template
// keep the editor away from the generated tmpls
$tpl->no_onclick = true;
// header rows
$tpl->new_cell(1,'label','Date');
$tpl->new_cell(1,'label','User');
$tpl->new_cell(1,'label','Changed');
$tpl->new_cell(1,'label','New value');
$tpl->new_cell(1,'label','Old value');
$status = 'status';
// allow to set a diffent name for status (field-name), eg. because status is already used for something else
if (!empty($cell['size']) && isset($tmpl->sel_options[$cell['size']]) && is_array($value))
{
$status = $cell['size'];
foreach($value as &$row)
{
$row[$status] = $row['status'];
}
}
// Add in links
self::$status_widgets['~link~'] = 'link-entry';
$tmpl->sel_options[$status]['~link~'] = lang('link');
$tmpl->sel_options[$status]['user_agent_action'] = lang('User-agent & action');
// adding custom fields automatically to status-widgets, no need for each app to do that
foreach(config::get_customfields($app,true) as $cf_name => $cf_data)
{
// add cf label, if not set by app
if (!isset($tmpl->sel_options[$status]['#'.$cf_name]))
{
$tmpl->sel_options[$status]['#'.$cf_name] = lang($cf_data['label']);
}
if (isset(self::$status_widgets['#'.$cf_name])) continue; // app set a status widget --> use that
if(!is_array($cf_data['values']) || !$cf_data['values'])
{
if (isset($GLOBALS['egw_info']['apps'][$cf_data['type']]))
{
self::$status_widgets['#'.$cf_name] = 'link-entry:'.$cf_data['type'];
}
else
{
self::$status_widgets['#'.$cf_name] = $cf_data['type'] != 'text' ? $cf_data['type'] : 'label';
}
}
elseif($cf_data['values']['@'])
{
self::$status_widgets['#'.$cf_name] = egw_customfields::get_options_from_file($cf_data['values']['@']);
}
elseif(count($cf_data['values']))
{
self::$status_widgets['#'.$cf_name] = $cf_data['values'];
}
}
if ($value) // autorepeated data-row only if there is data
{
// add "labels" for unsupported iCal properties, we just remove the '##' prefix
foreach($value as &$row)
{
if ($row['status'][0] == '#' && $row['status'][1] == '#' &&
isset($tmpl->sel_options[$status]) && !isset($tmpl->sel_options[$status][$row['status']]))
{
$tmpl->sel_options[$status][$row['status']] = substr($row['status'], 2);
}
}
$tpl->new_cell(2,'date-time','','${row}[user_ts]',array('readonly' => true));
$tpl->new_cell(2,'select-account','','${row}[owner]',array('readonly' => true));
// if $sel_options[status] is set, use them and a readonly selectbox
if (isset($tmpl->sel_options[$status]))
{
$tpl->new_cell(2,'select','','${row}['.$status.']',array('readonly' => true));
}
else
{
$tpl->new_cell(2,'label','','${row}[status]',array('no_lang' => true));
}
// if $value[status-widgets] is set, use them together with the historylog-helper
// to display new_ & old_value in the specified widget, otherwise use a label
if (self::$status_widgets)
{
$tpl->new_cell(2,'historylog-helper','','${row}[new_value]',array('size' => '$row_cont[status]','no_lang' => true,'readonly' => true));
$tpl->new_cell(2,'historylog-helper','','${row}[old_value]',array('size' => '$row_cont[status]','no_lang' => true,'readonly' => true));
}
else
{
$tpl->new_cell(2,'label','','${row}[new_value]',array('no_lang' => true));
$tpl->new_cell(2,'label','','${row}[old_value]',array('no_lang' => true));
}
array_unshift($value,false); // addjust index to start with 1, as we have a header-row
}
$tpl->data[0] = array(
'c1' => 'th',
'c2' => 'row',
);
$tpl->size = '100%';
$cell['size'] = $cell['name'];
$cell['type'] = 'template';
$cell['name'] = $tpl->name;
$cell['obj'] = &$tpl;
return True; // extra Label is ok
}
}

View File

@ -1,885 +0,0 @@
<?php
/**
* eGroupWare eTemplate Extension - Link Widgets / UI for the link class
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage extensions
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @copyright 2002-16 by RalfBecker@outdoor-training.de
* @version $Id$
*/
use EGroupware\Api;
/**
* eTemplate Extension: several widgets as user-interface for the link-class
*
* All widgets use the link-registry, to "know" which apps use popups (and what size).
* Participating apps need to register a proper "search_link" hook - see eTemplate-reference (LinkWidgets) for info.
* If run in a popup and the app uses no popups, a target will be set, to open a new full decorated window.
*
* The class contains the following widgets:
* - link: Show a link to one linked entry specified by an array with keys app, id and optional title,
* help-message and extra_args (array with additional get parameters)
* Optionally the application can be specified as option and the value can be just the id.
* - link-to: Widget to create links to an other entries of link-aware apps
* If the variables $data['widget_id']['to_app'] = $app and $data['widget_id']['to_id'] = $entry_id
* are set, this widget creates the links without further interaction with the calling code.
* If the entry does not yet exist, the widget returns an array with the new links in the id. After the
* entry was successfuly created, bolink::link($app,$new_id,$arr) has to be called to create the links!
* - link-list: Widget to show the links to an entry in a table with an unlink icon for each link. Needs the same
* pair of variables as link-to widget and needs to have the same id, as the data is shared with link-to.
* - link-string: comma-separated list of link-titles with a link to its view method, value is like get_links()
* or array with keys to_app and to_id (widget calls then get_links itself)
* - link-add: Add a new entry of the select app, which is already linked to a given entry
* - link-entry: Allow to select an entry of a selectable or in options specified app
* - link-apps: Select an app registered in the link system, options: '' or 'add'
*
*<code>
* $content[$name] = array(
* 'to_app' => // I string appname of the entry to link to
* 'to_id' => // IO int id of the entry to link to, for new entries 0, returns the array with new links
* // the following params apply only for the link-to widget!
* 'no_files' => // I boolean suppress attach-files, default no
* 'show_deleted' => // I Show links that are marked as deleted, being held for purge
* 'search_label' => // I string label to use instead of search
* 'link_label' => // I string label for the link button, default 'Link'
* // optional only for the link-add widget and link-entry widget
* 'extra' => // I array with extra parameters, eg. array('cat_id' => 15), or string to add in onclick search for link-entry
* //eg. ",values2url(this.form,'start,end,duration,participants,recur_type,whole_day')"
* 'query' => // I preset for the query
* 'current' => // I currently select id
* // optional for link-string:
* 'only_app' => // I string with appname, eg. 'projectmananager' to list only linked projects
* 'link_type' => // I string with sub-type key to list only entries of that type
* );
*</code>
*
* This widget is independent of the UI as it only uses etemplate-widgets and has therefore no render-function.
*/
class link_widget
{
/**
* @var array exported methods of this class
*/
var $public_functions = array(
'pre_process' => True,
'post_process' => True,
);
/**
* @var array availible extensions and there names for the editor
*/
var $human_name = array(
'link' => 'Link',
'link-to' => 'LinkTo',
'link-list' => 'LinkList',
'link-string' => 'LinkString',
'link-add' => 'LinkEntry',
'link-entry' => 'Select entry',
'link-apps' => 'LinkApps',
);
/**
* @var boolean $debug switches debug-messages on and off
*/
var $debug = False;
/**
* Flag that ajax_search needs to add onchange line
*
*/
const AJAX_NEED_ONCHANGE = 987;
/**
* Limit display of links to given number to not run into memory_limit for huge number of links
*/
const LIMIT_LINKS = 1000;
/**
* pre-processing of the extension
*
* This function is called before the extension gets rendered
*
* @param string $name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param object &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process($name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl)
{
$extension_data['type'] = $type = $cell['type'];
$extension_data['needed'] = $cell['needed'];
$help = $cell['help'] ? (is_array($value) && !empty($value['help']) ? $value['help'] : $cell['help']) : lang('view this linked entry in its application');
if ((in_array($type,array('link-to','link-add','link-entry')) && !$value) && ($cell['readonly'] || $readonlys))
{
//echo "<p>link-to is readonly, cell=".print_r($cell,true).", readonlys=".print_r($readonlys).", value='$value'</p>\n";
// readonly ==> omit the whole widget
$value = '';
$cell = $tmpl->empty_cell();
$extension_data = null;
return;
}
if (!is_array($value) && in_array($type,array('link-to','link-list','link-add')))
{
$value = array(
'to_id' => $value,
'to_app' => $GLOBALS['egw_info']['flags']['currentapp']
);
}
if ($this->debug)
{
echo "<p>link_widget::pre_process($name,$value,".print_r($cell,true).",$readonlys,,)</p>\n";
echo "<p>start: $cell[type][$name]::pre_process: value ="; _debug_array($value);
echo "extension_data[$cell[type]][$name] ="; _debug_array($extension_data);
}
switch ($cell['type'])
{
case 'link':
$cell['readonly'] = True; // set it readonly to NOT call our post_process function
$extension_data = null;
$cell['no_lang'] = 1;
$link = $target = $popup = '';
if (!is_array($value) && $value && isset($GLOBALS['egw_info']['apps'][$cell['size']]))
{
$value = array(
'id' => $value,
'app' => $cell['size'],
);
$cell['size'] = '';
}
if ($value['app'] && $value['id'])
{
$view = egw_link::view($value['app'],$value['id']);
$link = $view['menuaction']; unset($view['menuaction']);
foreach($view as $var => $val)
{
$link .= '&'.$var.'='.$val;
}
if (isset($value['extra_args']))
{
foreach($value['extra_args'] as $var => $val)
{
$link .= '&'.$var.'='.$val;
}
}
if (!($popup = egw_link::is_popup($value['app'],'view')) &&
etemplate::$request->output_mode == 2) // we are in a popup
{
$target = '_blank';
}
if (!$cell['help'])
{
$cell['help'] = $value['help'];
$cell['no_lang'] = 2;
}
}
elseif (!$value['title'])
{
$cell = $tmpl->empty_cell();
$cell['readonly'] = True; // set it readonly to NOT call our post_process function
$extension_data = null;
return;
}
$cell['type'] = 'label';
// size: [b[old]][i[talic]],[link],[activate_links],[label_for],[link_target],[link_popup_size],[link_title]
list($cell['size']) = explode(',',$cell['size']);
// Pass link through framework's handler
if(!$popup) $link = str_replace(',','%2C',egw::link('/index.php?menuaction='.$link,false,$value['app']));
$cell['size'] .= ','.$link.',,,'.$target.','.$popup.','.$value['extra_title'];
$value = $value['title'] ? $value['title'] : egw_link::title($value['app'],$value['id']);
return true;
case 'link-string':
$str = '';
if ($value && !is_array($value) && $cell['size'])
{
$value = array('to_id' => $value);
list($value['to_app'],$value['only_app']) = explode(',',$cell['size']);
}
if ($value['to_id'] && $value['to_app'])
{
$value = egw_link::get_links($value['to_app'], $value['to_id'], $only_app = $value['only_app'],
'link_lastmod DESC', true, $value['show_deleted'], self::LIMIT_LINKS);
if ($only_app)
{
foreach($value as $key => $id)
{
$value[$key] = array(
'id' => $id,
'app' => $only_app,
);
}
}
}
if (is_array($value))
{
foreach ($value as $link)
{
$str .= ($str !== '' ? ', ' : '') . self::link2a_href($link,$help);
}
}
$cell['type'] = 'html';
$cell['readonly'] = True; // set it readonly to NOT call our post_process function
$extension_data = null;
$value = $str;
return True;
case 'link-add':
$apps = egw_link::app_list($type == 'link-add' ? 'add_app' : 'query');
if (!$apps || !$value['to_id'] || is_array($value['to_id'])) // cant do an add without apps or already created entry
{
$cell = $tmpl->empty_cell();
return;
}
asort($apps); // sort them alphabetic
$value['options-add_app'] = array();
foreach($apps as $app => $label)
{
$link = $GLOBALS['egw']->link('/index.php',egw_link::add($app,$value['to_app'],$value['to_id'])+
(is_array($value['extra']) ? $value['extra'] : array()));
if (($popup = egw_link::is_popup($app,'add')))
{
list($w,$h) = explode('x',$popup);
$action = "window.open('$link','_blank','width=$w,height=$h,location=no,menubar=no,toolbar=no,scrollbars=yes,status=yes');";
}
else
{
$action = "location.href = '$link';";
}
$value['options-add_app'][$action] = $label;
// modify add_app default to the action used as value
if (isset($value['add_app']) && $app == $value['add_app']) $value['add_app'] = $action;
}
$tpl = new etemplate('etemplate.link_widget.add');
break;
case 'link-to':
$GLOBALS['egw_info']['flags']['include_xajax'] = true;
if ($value['search_label'] && $extension_data['search_label'] != $value['search_label']) $value['search_label'] = lang($value['search_label']);
$extension_data = $value;
$tpl = new etemplate('etemplate.link_widget.to');
if ($value['link_label']) $tpl->set_cell_attribute('create','label',$value['link_label']);
if ($value['search_label']) $tpl->set_cell_attribute('search','label',$value['search_label']);
self::get_sub_types($cell, $value, $tpl);
break;
case 'link-list':
$app = $value['to_app'];
$id = isset($extension_data['to_id']) ? $extension_data['to_id'] : $value['to_id'];
if ($this->debug)
{
echo "<p>link-list-widget[$name].preprocess: value="; _debug_array($value);
}
if (!isset($value['title']))
{
$value['title'] = egw_link::title($app,$id);
}
$links = egw_link::get_links($app, $id, '', 'link_lastmod DESC', true, $value['show_deleted'], self::LIMIT_LINKS);
$value['anz_links'] = count($links);
$extension_data = $value;
if (!count($links))
{
$cell = $tmpl->empty_cell();
$value = '';
return True;
}
$value['link_list_format'] = $GLOBALS['egw_info']['user']['preferences']['common']['link_list_format'];
$tpl = new etemplate('etemplate.link_widget.list');
for($row=$tpl->rows-1; list(,$link) = each($links); ++$row)
{
$value[$row] = $link;
$value[$row]['title'] = egw_link::title($link['app'],($link['app'] == egw_link::VFS_APPNAME&&!is_array($link['id'])?egw_vfs::decodePath($link['id']):$link['id']),$link);
if (!is_array($link['id']))
{
$value[$row]['view'] = egw_link::view($link['app'],$link['id'],$link);
if (!($value[$row]['popup'] = egw_link::is_popup($link['app'],'view',$link)) &&
etemplate::$request->output_mode == 2) // we are in a popup
{
$value[$row]['target'] = '_blank'; // we create a new window as the linked page is no popup
}
}
if ($link['app'] == egw_link::VFS_APPNAME)
{
$value[$row]['target'] = '_blank';
$value[$row]['label'] = 'Delete';
$value[$row]['help'] = lang('Delete this file');
if ($value['link_list_format'] != 'text')
{
$value[$row]['title'] = preg_replace('/: ([^ ]+) /',': ',$value[$row]['title']); // remove mime-type, it's alread in the icon
}
$value[$row]['icon'] = egw_link::vfs_path($link['app2'],$link['id2'],$link['id'],true);
}
else
{
$value[$row]['icon'] = egw_link::get_registry($value[$row]['app'], 'icon');
$value[$row]['label'] = 'Unlink';
$value[$row]['help'] = lang('Remove this link (not the entry itself)');
if(!egw_link::is_popup($link['app'],'view') && etemplate::$request->output_mode == 2)
{
// If link doesn't want a popup, make sure to open it in appropriate tab of main window
$value[$row]['view'] = "javascript:if(typeof opener.top.framework != 'undefined') {
opener.top.egw_appWindowOpen('{$link['app']}','".egw::link('/index.php',$value[$row]['view'])."');
} else {
opener.open('".egw::link('/index.php',$value[$row]['view'])."','".$value[$row]['target']."');
}";
}
}
}
break;
case 'link-entry':
if ($cell['readonly'] || $readonlys)
{
if(!is_array($value))
{
if (strpos($value,':') !== false) list($app,$value) = explode(':',$value,2);
$value = array('app' => $app ? $app : $cell['size'],'id' => $value);
}
$value = self::link2a_href($value,$help);
$cell['type'] = 'html';
$cell['readonly'] = true;
$extension_data = null;
return true;
}
$GLOBALS['egw_info']['flags']['include_xajax'] = true;
$tpl = new etemplate('etemplate.link_widget.entry');
$options = $cell['size'] ? explode(',',$cell['size']) : array();
$app = $extension_data['app'] = $options[0];
$link_type = $extension_data['link_type'];
// handle extra args for onclick like: values2url(this.form,'start,end,duration,participants,recur_type,whole_day')+'&exec[event_id]=
if ( isset($value) && is_array($value) && isset($value['extra']) )
{
//echo '<p>extra='.htmlspecialchars($value['extra'])."</p>\n";
//something like: values2url(this.form,'start,end,duration,participants,recur_type,whole_day')+'&exec[event_id]=
$on_click_string =& $tpl->get_cell_attribute('search','onclick');
$on_click_string = str_replace(');',','.$value['extra'].');',$on_click_string);
//echo htmlspecialchars($on_click_string);
}
if ($value) // show pre-selected entry in select-box and not the search
{
if (is_array($value))
{
if (isset($value['current']))
{
list($app,$id) = explode(':',$value['current'], 2);
if ($app) unset($value['default_sel']); // would overwrite $app!
}
}
else
{
// add selected-entry plus "new search" to the selectbox-options
if (!isset($app) || strpos($value,':') !== false)
{
list($app,$id) = explode(':',$value, 2);
}
else
{
$id = $value;
}
}
$titles = array();
foreach(explode(',',$id) as $id)
{
if ($id)
{
if (!($title = egw_link::title($app,$id)))
{
$title = $app.': #'.$id;
}
$titles[$id] = $title;
}
}
if ($titles)
{
if ($cell['onchange']) $titles[0] = lang('Show all / cancel filter');
$titles[''] = lang('new search').' ...';
$selectbox =& $tpl->get_widget_by_name('id');
$selectbox['sel_options'] = $titles;
// remove link_hide class from select-box-line
$span =& $tpl->get_cell_attribute('select_line','span');
$span = str_replace('link_hide','',$span);
// add link_hide class to search_line
$span =& $tpl->get_cell_attribute('search_line','span');
$span .= ' link_hide';
unset($span);
}
}
if ($extension_data['app'] && count($options) <= 1) // no app-selection, using app given in first option
{
$tpl->disable_cells('app');
$onchange =& $tpl->get_cell_attribute('search','onclick');
$onchange = str_replace("document.getElementById(form::name('app')).value",'\''.$cell['size'].'\'',$onchange);
unset($onchange);
}
// store now our values in extension_data to preserve them upon submits (after empty title submit for example)
$extension_data['default'] = $value;
// adding possibility to get a default selection on app select, use for resource in calendar edit.participant
$value = array(
'app' => is_array($value) && isset($value['default_sel']) ? $value['default_sel'] : $app,
'no_app_sel' => !!$extension_data['app'],
'id' => is_array($value) ? $value['current'] : $id,
'query' => is_array($value) ? $value['query'] : '',
'blur' => $cell['blur'] ? lang($cell['blur']) :
(count($options) == 1 ? lang($app) : lang('Search')),
'extra' => $cell['onchange'] ? ','.self::AJAX_NEED_ONCHANGE : null, // store flang for ajax_search, to display extra_line required by onchange
);
if ($cell['needed']) $value['class'] = 'inputRequired';
if ($options) // limit the app-selectbox to the given apps
{
$tpl->set_cell_attribute('app','type','select');
$tpl->set_cell_attribute('app','no_lang',true);
$apps = egw_link::app_list('query');
asort($apps); // sort them alphabetic
foreach($apps as $app => $label)
{
if (!in_array($app,$options)) unset($apps[$app]);
}
$value['options-app'] = $apps;
}
self::get_sub_types($cell, $value, $tpl);
break;
case 'link-apps':
$apps = egw_link::app_list($cell['size'] ? $cell['size'] : 'query');
if (!$apps) // cant do an add without apps or already created entry
{
$cell = $tmpl->empty_cell();
return;
}
asort($apps); // sort them alphabetic
$cell['sel_options'] = $apps;
$cell['no_lang'] = True; // already translated
$cell['type'] = 'select';
return true;
}
$cell['size'] = $cell['name'];
$cell['type'] = 'template';
$cell['name'] = $tpl->name;
$cell['obj'] =& $tpl;
// keep the editor away from the generated tmpls
$tpl->no_onclick = true;
if ($this->debug)
{
echo "<p>end: $type"."[$name]::pre_process: value ="; _debug_array($value);
}
return True; // extra Label is ok
}
/**
* return a_href to view a linked entry
*
* @param array $link array with values for keys 'id' and 'app'
* @param string $help=''
* @return string
*/
static function link2a_href(array $link,$help='')
{
if (($popup = egw_link::is_popup($link['app'], 'view', $link)))
{
list($w,$h) = explode('x',$popup);
$options = ' onclick="window.open(this,this.target,\'width='.(int)$w.',height='.(int)$h.',location=no,menubar=no,toolbar=no,scrollbars=yes,status=yes\'); return false;"';
}
elseif (etemplate::$request->output_mode == 2 || // we are in a popup
$link['app'] == egw_link::VFS_APPNAME || // or it's a link to an attachment
($target = egw_link::get_registry($link['app'],'view_target'))) // or explicit target set
{
$options = ' target="'.($target ? $target : '_blank').'"';
}
else
{
// Pass link through framework's handler
$href = str_replace(',','%2C',egw::link('/index.php',egw_link::view($link['app'],$link['id'],$link),$link['app']));
}
if ($help)
{
$options .= " onMouseOver=\"self.status='".addslashes(html::htmlspecialchars($help))."'; return true;\"";
$options .= " onMouseOut=\"self.status=''; return true;\"";
}
return html::a_href(
html::htmlspecialchars(egw_link::title($link['app'],($link['app']==egw_link::VFS_APPNAME?egw_vfs::decodePath($link['id']):$link['id']))),
$href ? $href : egw_link::view($link['app'],$link['id'],$link),'',$options);
}
/**
* postprocessing method, called after the submission of the form
*
* It has to copy the allowed/valid data from $value_in to $value, otherwise the widget
* will return no data (if it has a preprocessing method). The framework insures that
* the post-processing of all contained widget has been done before.
*
* Only used by select-dow so far
*
* @param string $name form-name of the widget
* @param mixed &$value the extension returns here it's input, if there's any
* @param mixed &$extension_data persistent storage between calls or pre- and post-process
* @param boolean &$loop can be set to true to request a re-submision of the form/dialog
* @param etemplate &$tmpl the eTemplate the widget belongs too
* @param mixed &value_in the posted values (already striped of magic-quotes)
* @return boolean true if $value has valid content, on false no content will be returned!
*/
function post_process($name,&$value,&$extension_data,&$loop,&$tmpl,$value_in)
{
//echo "<p>link_widget::post_process('$name',value=".print_r($value,true).",ext=".print_r($extension_data,true).",$loop,,value_in=".print_r($value_in,true)."</p>\n";
switch($extension_data['type'])
{
case 'link-entry':
//error_log(__METHOD__.__LINE__.array2string(array('data'=>$value,'value in'=>$value_in,'extension_data'=>$extension_data,'source'=>function_backtrace())));
if (!$value_in['id'] && $extension_data['needed'])
{
$tmpl->set_validation_error($name,lang('Field must not be empty !!!'),'');
return true;
}
$defaultData = false;
// beware: default may be something like Array([link_type] => [query] => [id] => ) so take care for id, in case it is empty AND needed
if (is_array($extension_data['default']) && !empty($extension_data['default']))
{
// this may fail, if $extension_data['default'][0] is set on purpose
foreach($extension_data['default'] as $k => $v)
{
if ($v)
{
$defaultData=true;
if ($k==0 && !empty($value_in['id'])) // we have a valid incomming id, we intend to use that
{
$defaultData=false;
continue;
}
break;
}
}
if ($defaultData)
{
$value = $extension_data['default'];
$value['current'] = $extension_data['app'] ? $value_in['id'] : $value_in['app'].':'.$value_in['id'];
// we take care for id, in case it is empty AND needed
if(empty($value['id']) && $extension_data['needed']) $value['id'] = $value['current'];
}
}
if($defaultData === false)
{
// this was the line before the default opt, not sure it works well in all case
$value = $extension_data['app'] ? $value_in['id'] : $value['app'].':'.$value_in['id'];
}
//error_log(__METHOD__.__LINE__.array2string(array('return'=>$value)));
return true;
case 'link-apps':
if (!$value_in && $extension_data['needed'])
{
$tmpl->set_validation_error($name,lang('Field must not be empty !!!'),'');
return true;
}
$value = $value_in;
return !!$value;
}
$buttons = array('search','create','new','upload','attach');
while (!$button && list(,$bname) = each($buttons))
{
$button = $value[$bname] ? $bname : '';
}
if (is_array($value['unlink']))
{
$button = 'unlink';
list($unlink) = @each($value['unlink']);
}
unset($value[$button]);
unset($value['msg']);
unset($extension_data['msg']);
if (is_array($extension_data))
{
$value = is_array($value) ? array_merge($extension_data,$value) : $extension_data;
}
if ($button && $this->debug)
{
echo "<p>start: link_widget[$name]::post_process: button='$button', unlink='$unlink', value ="; _debug_array($value);
}
switch ($button)
{
case 'create':
if ($value['to_app']) // make the link
{
$link_id = egw_link::link($value['to_app'],$value['to_id'],
$value['app'],$value['id'],$value['remark']);
$value['remark'] = $value['query'] = '';
if (isset($value['primary']) && !$value['anz_links'] )
{
$value['primary'] = $link_id;
}
}
// fall-trough
case 'search':
case 'new':
$extension_data = $value;
$loop = True;
break;
case 'attach':
$name = preg_replace('/^exec\[([^]]+)\](.*)$/','\\1\\2',$name); // remove exec prefix
if (is_array($value['file']) && $value['to_app'] &&
!empty($value['file']['tmp_name']) && $value['file']['tmp_name'] != 'none')
{
if (!$value['to_id'] || is_array($value['to_id'])) // otherwise the webserver deletes the file
{
if (is_dir($GLOBALS['egw_info']['server']['temp_dir']) && is_writable($GLOBALS['egw_info']['server']['temp_dir']))
{
$new_file = tempnam($GLOBALS['egw_info']['server']['temp_dir'],'egw_');
}
else
{
$new_file = $value['file']['tmp_name'].'+';
}
move_uploaded_file($value['file']['tmp_name'],$new_file);
$value['file']['tmp_name'] = $new_file;
}
if (!($link_id = egw_link::link($value['to_app'],$value['to_id'],
egw_link::VFS_APPNAME,$value['file'],$value['remark'])))
{
etemplate::set_validation_error($name.'[file]',lang('Error copying uploaded file to vfs!'));
}
else
{
$value['remark'] = '';
if (isset($value['primary']) && !$value['anz_links'] )
{
$value['primary'] = $link_id;
}
unset($value['comment']);
unset($value['file']);
}
}
else
{
etemplate::set_validation_error($name.'[file]',lang('You need to select a file first!'));
}
$extension_data = $value;
$loop = True;
break;
case 'unlink':
if ($this->debug)
{
//echo "<p>unlink(link-id=$unlink,$value[to_app],$value[to_id])</p>\n";
if (is_array($value['to_id'])) _debug_array($value['to_id']);
}
egw_link::unlink2($unlink,$value['to_app'],$value['to_id']);
if (is_array($value['to_id']))
{
$extension_data['to_id'] = $value['to_id']; // else changes from unlink get lost
}
$loop = True;
break;
}
$value['button'] = $button;
if ($this->debug)
{
echo "<p>end: link_widget[$name]::post_process: value ="; _debug_array($value);
}
return True;
}
/**
* Get sub-types for the current application
*/
private static function get_sub_types($cell, &$value, &$tpl) {
// Get sub-types
if($value['options-app']) {
$apps = $value['options-app'];
} else {
$apps = egw_link::app_list($cell['size'] ? $cell['size'] : 'query');
asort($apps); // sort them alphabetic
}
$current_app = $value['app'] ? $value['app'] : key($apps);
if(is_array(egw_link::$app_register[$current_app]['types'])) {
foreach(egw_link::$app_register[$current_app]['types'] as $key => $settings) {
$value['options-link_type'][$key] = $settings['name'];
}
$span =& $tpl->get_cell_attribute('type_box','span');
$span = str_replace('type_hide','type_show',$span);
unset($span);
}
}
/**
* Ajax callback to search in $app for $pattern, result is displayed in $id
*
* Called via onClick from etemplate.link_widget.(to|entry)'s search button
*
* @param string $app app-name to search
* @param string $pattern search-pattern
* @param string $id_res id of selectbox to show the result
* @param string $id_hide id(s) of the search-box/-line to hide after a successful search
* @param string $id_show id(s) of the select-box/-line to show after a successful search
* @param string $id_input id of the search input-field
* @param string $etemplate_exec_id of the calling etemplate, to upate the allowed ids
* @param string $extra optionnal extra search arguments
* @return string xajax xml response
*/
static function ajax_search($app,$type,$pattern,$id_res,$id_hide,$id_show,$id_input,$etemplate_exec_id,$extra=array())
{
$extra_array = array();
if (!empty($extra))
{
//parse $extra as a get url
parse_str($extra,$extra_array) ;
// securize entries as they were html encoded and so not checked on the first pass
_check_script_tag($extra_array,'extra_array');
}
if ($pattern == lang('Search') || $pattern == lang($app)) $pattern = '';
if (empty($extra_array))
{
$search = $pattern;
}
else
{
$extra_array['search']= $pattern;
$search = $extra_array;
}
// open request
if ($etemplate_exec_id) $request = Api\Etemplate\Request::read($etemplate_exec_id);
$response = new xajaxResponse();
$options = array();
//$args = func_get_args(); $response->addAlert("link_widget::ajax_search('".implode("',\n'",$args)."')\n calling link->query( $app , $search, $type )" );
//$args = func_get_args(); error_log(__METHOD__."('".implode("','",$args)."')");
if($type) {
$options['type'] = $type;
}
if (!($found = egw_link::query($app,$search,$options))) // ignore the blur-text
{
$GLOBALS['egw']->translation->add_app('etemplate');
$response->addAlert(lang('Nothing found - try again !!!'));
$response->addScript("document.getElementById('$id_input').select();");
}
else
{
$script = "var select = document.getElementById('$id_res');\nselect.options.length=0;\n";
// check if we need to add extra line to produce an onchange to submit the form
if (($data = $request->get_to_process($id_input)) && $data['maxlength'] == self::AJAX_NEED_ONCHANGE)
{
$script .= "opt = select.options[select.options.length] = new Option('".addslashes(lang('%1 entries found, select one ...',count($found)))."',' ');\n";
}
foreach($found as $id => $option)
{
if (!is_array($option)) $option = array('label' => $option);
// xajax uses xml to transport the label, therefore we have to replace not only CR, LF
// (not allowed unencoded in Javascript strings) but also all utf-8 C0 and C1 plus CR and LF
$option['label'] = preg_replace('/[\000-\037\177-\237]/u',' ',$option['label']);
$script .= "opt = select.options[select.options.length] = new Option('".addslashes($option['label'])."','".addslashes($id)."');\n";
if (count($option) > 1)
{
foreach($option as $name => $value)
{
if ($name != 'label') $script .= "opt.$name = '".addslashes($value)."';\n";
}
}
}
$script .= "select.options[select.options.length] = new Option('".addslashes(lang('New search').' ...')."','');\n";
foreach(explode(',',$id_show) as $id)
{
$script .= "document.getElementById('$id').style.display='inline';\n";
}
foreach(explode(',',$id_hide) as $id)
{
$script .= "document.getElementById('$id').style.display='none';\n";
}
//$response->addAlert($script);
$response->addScript($script);
}
// store new allowed id's in the eT request
if ($request)
{
$data = $request->get_to_process($id_res);
//error_log($id_res.'='.array2string($data));
$data['allowed'] = $found ? array_keys($found) : array();
$request->set_to_process($id_res,$data);
// update id, if request changed it (happens if the request data is stored direct in the form)
if ($etemplate_exec_id != ($new_id = $request->id()))
{
$response->addAssign('etemplate_exec_id','value',$new_id);
}
}
return $response->getXML();
}
/**
* Ajax callback to search for sub-types for $app, result is displayed in $id_res
*
* Called via onChange from etemplate.link_widget.(to|entry)'s app list
*
* @param string $app app-name to search
* @param string $id_res id of selectbox to show the result
* @param string $etemplate_exec_id of the calling etemplate, to upate the allowed ids
* @return string xajax xml response
*/
static function ajax_get_types($app,$id_res,$etemplate_exec_id)
{
// open request
if ($etemplate_exec_id) $request = Api\Etemplate\Request::read($etemplate_exec_id);
$response = new xajaxResponse();
//$args = func_get_args(); $response->addAlert("link_widget::ajax_search('".implode("',\n'",$args)."')\n calling link->query( $app , $search )" );
//$args = func_get_args(); error_log(__METHOD__."('".implode("','",$args)."')");
$script = "var select = document.getElementById('$id_res');\nselect.options.length=0;\n";
if(is_array(egw_link::$app_register[$app]['types']))
{
$found = egw_link::$app_register[$app]['types'];
foreach(egw_link::$app_register[$app]['types'] as $id => $option)
{
$option = array('label' => $option['name']);
$script .= "opt = select.options[select.options.length] = new Option('".addslashes($option['label'])."','".addslashes($id)."');\n";
if (count($option) > 1)
{
foreach($option as $name => $value)
{
if ($name != 'label') $script .= "opt.$name = '".addslashes($value)."';\n";
}
}
}
$script .= "document.getElementById('$id_res').parentNode.style.display='inline';\n";
}
else
{
$script .= "document.getElementById('$id_res').parentNode.style.display='none';\n";
}
$response->addScript($script);
// store new allowed id's in the eT request
if ($request)
{
$data = $request->get_to_process($id_res);
//error_log($id_res.'='.array2string($data));
$data['allowed'] = $found ? array_keys($found) : array();
$request->set_to_process($id_res,$data);
// update id, if request changed it (happens if the request data is stored direct in the form)
if ($etemplate_exec_id != ($new_id = $request->id()))
{
$response->addAssign('etemplate_exec_id','value',$new_id);
}
}
return $response->getXML();
}
}

View File

@ -1,99 +0,0 @@
<?php
/**
* eGroupWare eTemplate Extension - Manual Widget
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/
/**
* eTemplate Extension: Manual widget
*
* This widget is an icon which opens the online help system (manual) in a popup.
*
* With the value or the name of the widget, you can specify a certain manual page
* (eg. ManualAddressbook). Additional params can be past to the manual app with
* $GLOBALS['egw_info']['flags']['params']['manual'].
* If no page is set after that two mechanisms the URL will contains the referer.
*
* @package etemplate
* @subpackage extensions
* @author RalfBecker-AT-outdoor-training.de
* @license GPL
*/
class manual_widget
{
/**
* exported methods of this class
* @var array $public_functions
*/
var $public_functions = array(
'pre_process' => True,
);
/**
* availible extensions and there names for the editor
*
* @var string/array $human_name
*/
var $human_name = 'Manual';
/**
* @var array
*/
/**
* Constructor of the extension
*
* @param string $ui '' for html
*/
function __construct($ui)
{
$this->ui = $ui;
}
/**
* pre-processing of the extension
*
* This function is called before the extension gets rendered
*
* @param string $name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param object &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process($name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl)
{
$link = array('menuaction' => 'manual.uimanual.view');
if (is_array($GLOBALS['egw_info']['flags']['params']['manual']))
{
$link = array_merge($link,$GLOBALS['egw_info']['flags']['params']['manual']);
}
$page = $cell['name'] ? $cell['name'] : $value;
if (!empty($page))
{
$link['page'] = $page;
}
if (!$link['page'])
{
$link['referer'] = ($_SERVER['HTTPS'] ? 'https://' : 'http://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
}
$link = egw::link('/index.php',$link);
$cell['type'] = 'button';
$cell['size'] = 'manual-small';
$cell['onclick'] = $GLOBALS['egw']->framework->open_manual_js($link).'; return false;';
if (!$cell['label']) $cell['label'] = 'Manual';
if (!$cell['help']) $cell['help'] = /*lang(*/'Open the online help.'/*)*/;
if (!$cell['readonly'] && !isset($GLOBALS['egw_info']['user']['apps']['manual']))
{
$cell['readonly'] = true; // we disable / remove the button, if use has no run-rights for the manual
}
return False; // no extra label, label is tooltip for image
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,128 +0,0 @@
<?php
/**
* eGroupWare eTemplate Extension - Path Widgets
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/
/**
* eTemplate Extension: widget to display a path with clickable components
*
* The value is an array with id => label pairs.
* Returned will be the id of the clicked component or nothing at all.
*
* @package etemplate
* @subpackage extensions
* @author RalfBecker-AT-outdoor-training.de
* @license GPL
*/
class path_widget
{
/**
* exported methods of this class
* @var array
*/
var $public_functions = array(
'pre_process' => True,
'post_process' => True,
);
/**
* availible extensions and there names for the editor
* @var string
*/
var $human_name = 'clickable path';
/**
* Constructor of the extension
*
* @param string $ui '' for html
*/
function __construct($ui)
{
$this->ui = $ui;
}
/**
* pre-processing of the extension
*
* This function is called before the extension gets rendered
*
* @param string $name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param object &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process($name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl)
{
$seperator = $cell['size'] ? $cell['size'] : '/';
$extension_data = (array) $value;
if (!is_array($value) || !count($value))
{
$cell = soetemplate::empty_cell();
$cell['label'] = $seperator;
return true;
}
$cell_name = $cell['name'];
$cell['name'] = '';
$cell['type'] = 'hbox';
$cell['size'] = 0;
foreach ($value as $id => $label)
{
$sep = soetemplate::empty_cell();
$sep['label'] = $seperator;
soetemplate::add_child($cell,$sep);
unset($sep);
$button = soetemplate::empty_cell('button',$cell_name.'['.$id.']');
$button['label'] = $label;
$button['onchange'] = 1; // display as link
$button['no_lang'] = $cell['no_lang'];
$button['help'] = $cell['help'] ? $cell['help'] : lang($label)."($i)";
soetemplate::add_child($cell,$button);
unset($button);
}
return True; // extra Label Ok
}
/**
* postprocessing method, called after the submission of the form
*
* It has to copy the allowed/valid data from $value_in to $value, otherwise the widget
* will return no data (if it has a preprocessing method). The framework insures that
* the post-processing of all contained widget has been done before.
*
* Only used by select-dow so far
*
* @param string $name form-name of the widget
* @param mixed &$value the extension returns here it's input, if there's any
* @param mixed &$extension_data persistent storage between calls or pre- and post-process
* @param boolean &$loop can be set to true to request a re-submision of the form/dialog
* @param object &$tmpl the eTemplate the widget belongs too
* @param mixed &value_in the posted values (already striped of magic-quotes)
* @return boolean true if $value has valid content, on false no content will be returned!
*/
function post_process($name,&$value,&$extension_data,&$loop,&$tmpl,$value_in)
{
$value = '';
foreach((array)$value_in as $id => $pressed)
{
if ($pressed && isset($extension_data[$id]))
{
$value = $id;
break;
}
}
//echo "<p>select_widget::post_process('$name',value=".print_r($value,true).",".print_r($extension_data,true).",,,value_in=".print_r($value_in,true).")</p>\n";
return true;
}
}

View File

@ -1,598 +0,0 @@
<?php
/**
* eGroupWare eTemplate Extension - Select Widgets
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage extensions
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @copyright 2002-9 by RalfBecker@outdoor-training.de
* @version $Id$
*/
/**
* eTemplate Extension: several select-boxes with predefined eGW specific content
*
* This widgets replaces the not longer exiting phpgwapi.sbox class. The widgets are independent of the UI,
* as they only uses etemplate-widgets and therefore have no render-function.
*/
class select_widget
{
/**
* exported methods of this class
* @var array
*/
var $public_functions = array(
'pre_process' => True,
'post_process' => True,
);
/**
* availible extensions and their names for the editor
* @var array
*/
var $human_name = array(
'select-percent' => 'Select Percentage',
'select-priority' => 'Select Priority',
'select-access' => 'Select Access',
'select-country' => 'Select Country',
'select-state' => 'Select State', // US-states
'select-cat' => 'Select Category', // Category-Selection, size: -1=Single+All, 0=Single, >0=Multiple with size lines
'select-account' => 'Select Account', // label=accounts(default),groups,both
// size: -1=Single+not assigned, 0=Single, >0=Multiple
'select-year' => 'Select Year',
'select-month' => 'Select Month',
'select-day' => 'Select Day',
'select-dow' => 'Select Day of week',
'select-hour' => 'Select Hour', // either 0-23 or 12am,1am-11am,12pm,1pm-11pm
'select-number' => 'Select Number',
'select-app' => 'Select Application',
'select-lang' => 'Select Language',
'select-bool' => 'Select yes or no',
'select-timezone' => 'Select timezone', // select timezone
);
/**
* @var array
*/
var $monthnames = array(
0 => '',
1 => 'January',
2 => 'February',
3 => 'March',
4 => 'April',
5 => 'May',
6 => 'June',
7 => 'July',
8 => 'August',
9 => 'September',
10 => 'October',
11 => 'November',
12 => 'December'
);
/**
* Constructor of the extension
*
* @param string $ui '' for html
*/
function __construct($ui='')
{
foreach($this->monthnames as $k => $name)
{
if ($name)
{
$this->monthnames[$k] = lang($name);
}
}
$this->ui = $ui;
}
/**
* pre-processing of the extension
*
* This function is called before the extension gets rendered
*
* @param string $name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param object &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process($name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl)
{
list($rows,$type,$type2,$type3,$type4,$type5,$type6,$enhance) = explode(',',$cell['size']);
$extension_data['type'] = $cell['type'];
$readonly = $cell['readonly'] || $readonlys;
switch ($cell['type'])
{
case 'select-percent': // options: #row,decrement(default=10)
$decr = $type > 0 ? $type : 10;
for ($i=0; $i <= 100; $i += $decr)
{
$cell['sel_options'][intval($i)] = intval($i).'%';
}
$cell['sel_options'][100] = '100%';
if (!$rows || !empty($value))
{
$value = intval(($value+($decr/2)) / $decr) * $decr;
}
$cell['no_lang'] = True;
break;
case 'select-priority':
$cell['sel_options'] = array('none','low','normal','high');
break;
case 'select-bool': // equal to checkbox, can be used with nextmatch-customfilter to filter a boolean column
$cell['sel_options'] = array(0 => 'no',1 => 'yes');
break;
case 'select-access':
$cell['sel_options'] = array(
'private' => 'Private',
'public' => 'Global public',
'group' => 'Group public'
);
break;
case 'select-country': // #Row|Extralabel,1=use country name, 0=use 2 letter-code,custom country field name
if($type == 0 && $type2)
{
$custom_label = is_numeric($type2) ? 'Custom' : $type2;
$cell['sel_options'] = array('-custom-' => lang($custom_label)) + $GLOBALS['egw']->country->countries();
}
else
{
$cell['sel_options'] = $GLOBALS['egw']->country->countries();
}
if (($extension_data['country_use_name'] = $type) && $value)
{
$value = $GLOBALS['egw']->country->country_code($value);
if (!isset($cell['sel_options'][$value]))
{
if($type2)
{
$cell['sel_options'][$value] = $value;
}
}
}
$cell['no_lang'] = True;
break;
case 'select-state':
$cell['sel_options'] = $GLOBALS['egw']->country->us_states();
$cell['no_lang'] = True;
break;
case 'select-cat': // !$type == globals cats too, $type2: extraStyleMultiselect, $type3: application, if not current-app, $type4: parent-id, $type5=owner (-1=global),$type6=show missing
if ($readonly) // for readonly we dont need to fetch all cat's, nor do we need to indent them by level
{
$cell['no_lang'] = True;
if ($value)
{
if (!is_array($value)) $value = explode(',',$value);
// Filter ACL
$value = $GLOBALS['egw']->categories->check_list(EGW_ACL_READ,implode(',',$value));
$value = explode(',',$value);
foreach($value as $key => $id)
{
if ($id && ($name = stripslashes($GLOBALS['egw']->categories->id2name($id))) && $name != '--')
{
$cell['sel_options'][$id] = $name;
}
else
{
if(!$type6)
{
unset($value[$key]); // remove not (longer) existing or inaccessible cats
}
elseif ($id) // Display id of no longer existing cat
{
$cell['sel_options'][$id] = $type6 == '2' ? $id : lang('Missing: %1',$id);
}
}
}
}
else
{
$value = '';
}
break;
}
if ((!$type3 || $type3 === $GLOBALS['egw']->categories->app_name) &&
(!$type5 || $type5 == $GLOBALS['egw']->categories->account_id))
{
$categories = $GLOBALS['egw']->categories;
}
else // we need to instanciate a new cat object for the correct application
{
$categories = new categories($type5,$type3);
}
// Allow text for global
$type = ($type && strlen($type) > 1 ? $type : !$type);
// we cast $type4 (parent) to int, to get default of 0 if omitted
foreach((array)$categories->return_sorted_array(0,False,'','','',$type,(int)$type4,true) as $cat)
{
$s = str_repeat('&nbsp;',$cat['level']) . stripslashes($cat['name']);
$cell['sel_options'][$cat['id']] = empty($cat['description']) ? $s : array(
'label' => $s,
'title' => $cat['description'],
);
}
// preserv unavailible cats (eg. private user-cats)
if ($value && ($unavailible = array_diff(is_array($value) ? $value : explode(',',$value),array_keys((array)$cell['sel_options']))))
{
$extension_data['unavailible'] = $unavailible;
}
$cell['size'] = $rows.($type2 ? ','.$type2 : '');
$cell['no_lang'] = True;
break;
case 'select-account': // options: #rows,{accounts(default)|both|groups|owngroups},{0(=lid)|1(default=name)|2(=lid+name),expand-multiselect-rows,not-to-show-accounts,...)}
//echo "<p>select-account widget: name=$cell[name], type='$type', rows=$rows, readonly=".(int)($cell['readonly'] || $readonlys)."</p>\n";
if($type == 'owngroups')
{
$type = 'groups';
$owngroups = true;
foreach($GLOBALS['egw']->accounts->membership() as $group) $mygroups[] = $group['account_id'];
}
// in case of readonly, we read/create only the needed entries, as reading accounts is expensive
if ($readonly)
{
$cell['no_lang'] = True;
if (!is_array($value) && strpos($value,',') !== false) $value = explode(',',$value);
foreach(is_array($value) ? $value : array($value) as $id)
{
$cell['sel_options'][$id] = !$id && !is_numeric($rows) ? lang($rows) :
$this->accountInfo($id,$acc,$type2,$type=='both');
}
break;
}
if ($this->ui == 'html' && $type != 'groups') // use eGW's new account-selection (html only)
{
$not = array_slice(explode(',',$cell['size']),4);
$help = (int)$cell['no_lang'] < 2 ? lang($cell['help']) : $cell['help'];
$onFocus = "self.status='".addslashes(htmlspecialchars($help))."'; return true;";
$onBlur = "self.status=''; return true;";
if ($cell['noprint'])
{
foreach(is_array($value) ? $value : (strpos($value,',') !== false ? explode(',',$value) : array($value)) as $id)
{
if ($id) $onlyPrint[] = $this->accountInfo($id,$acc,$type2,$type=='both');
}
$onlyPrint = $onlyPrint ? implode('<br />',$onlyPrint) : lang((int)$rows < 0 ? 'all' : $rows);
$noPrint_class = ' class="noPrint"';
}
if (($rows > 0 || $type3) && substr($name,-2) != '[]') $name .= '[]';
$value = $GLOBALS['egw']->uiaccountsel->selection($name,'eT_accountsel_'.str_replace(array('[','][',']'),array('_','_',''),$name),
$value,$type,$rows > 0 ? $rows : ($type3 ? -$type3 : 0),$not,' onfocus="'.$onFocus.'" onblur="'.$onBlur.'"'.$noPrint_class,
$cell['onchange'] == '1' ? 'this.form.submit();' : $cell['onchange'],
!empty($rows) && 0+$rows <= 0 ? lang($rows < 0 ? 'all' : $rows) : False);
if ($cell['noprint'])
{
$value = '<span class="onlyPrint">'.$onlyPrint.'</span>'.$value;
}
$cell['type'] = 'html';
$cell['size'] = ''; // is interpreted as link otherwise
etemplate::$request->set_to_process($name,'select');
if ($cell['needed']) etemplate::$request->set_to_process_attribute($name,'needed',$cell['needed']);
break;
}
$cell['no_lang'] = True;
$accs = $GLOBALS['egw']->accounts->get_list(empty($type) ? 'accounts' : $type); // default is accounts
foreach($accs as $acc)
{
if ($acc['account_type'] == 'u')
{
$cell['sel_options'][$acc['account_id']] = $this->accountInfo($acc['account_id'],$acc,$type2,$type=='both');
}
}
foreach($accs as $acc)
{
if ($acc['account_type'] == 'g' && (!$owngroups || ($owngroups && in_array($acc['account_id'],(array)$mygroups))))
{
$cell['sel_options'][$acc['account_id']] = $this->accountInfo($acc['account_id'],$acc,$type2,$type=='both');
}
}
break;
case 'select-year': // options: #rows,#before(default=3),#after(default=2)
$cell['sel_options'][''] = '';
if ($type <= 0) $type = 3;
if ($type2 <= 0) $type2 = 2;
if ($type > 100 && $type2 > 100 && $type > $type) { $y = $type; $type=$type2; $type2=$y; }
$y = date('Y')-$type;
if ($value && $value-$type < $y || $type > 100) $y = $type > 100 ? $type : $value-$type;
$to = date('Y')+$type2;
if ($value && $value+$type2 > $to || $type2 > 100) $to = $type2 > 100 ? $type2 : $value+$type2;
for ($n = 0; $y <= $to && $n < 200; ++$n)
{
$cell['sel_options'][$y] = $y++;
}
$cell['no_lang'] = True;
break;
case 'select-month':
$cell['sel_options'] = $this->monthnames;
$value = intval($value);
break;
case 'select-dow': // options: rows[,0=summaries befor days, 1=summaries after days, 2=no summaries[,extraStyleMultiselect]]
if (!defined('MCAL_M_SUNDAY'))
{
define('MCAL_M_SUNDAY',1);
define('MCAL_M_MONDAY',2);
define('MCAL_M_TUESDAY',4);
define('MCAL_M_WEDNESDAY',8);
define('MCAL_M_THURSDAY',16);
define('MCAL_M_FRIDAY',32);
define('MCAL_M_SATURDAY',64);
define('MCAL_M_WEEKDAYS',62);
define('MCAL_M_WEEKEND',65);
define('MCAL_M_ALLDAYS',127);
}
$weekstart = $GLOBALS['egw_info']['user']['preferences']['calendar']['weekdaystarts'];
$cell['sel_options'] = array();
if ($rows >= 2 && !$type)
{
$cell['sel_options'] = array(
MCAL_M_ALLDAYS => 'all days',
MCAL_M_WEEKDAYS => 'working days',
MCAL_M_WEEKEND => 'weekend',
);
}
if ($weekstart == 'Saturday') $cell['sel_options'][MCAL_M_SATURDAY] = 'saturday';
if ($weekstart != 'Monday') $cell['sel_options'][MCAL_M_SUNDAY] = 'sunday';
$cell['sel_options'] += array(
MCAL_M_MONDAY => 'monday',
MCAL_M_TUESDAY => 'tuesday',
MCAL_M_WEDNESDAY=> 'wednesday',
MCAL_M_THURSDAY => 'thursday',
MCAL_M_FRIDAY => 'friday',
);
if ($weekstart != 'Saturday') $cell['sel_options'][MCAL_M_SATURDAY] = 'saturday';
if ($weekstart == 'Monday') $cell['sel_options'][MCAL_M_SUNDAY] = 'sunday';
if ($rows >= 2 && $type == 1)
{
$cell['sel_options'] += array(
MCAL_M_ALLDAYS => 'all days',
MCAL_M_WEEKDAYS => 'working days',
MCAL_M_WEEKEND => 'weekend',
);
}
$value_in = $value;
$value = array();
foreach($cell['sel_options'] as $val => $lable)
{
if (($value_in & $val) == $val)
{
$value[] = $val;
if ($val == MCAL_M_ALLDAYS ||
$val == MCAL_M_WEEKDAYS && $value_in == MCAL_M_WEEKDAYS ||
$val == MCAL_M_WEEKEND && $value_in == MCAL_M_WEEKEND)
{
break; // dont set the others
}
}
}
if (!$readonly)
{
etemplate::$request->set_to_process($name,'ext-select-dow');
}
$cell['size'] = $rows.($type2 ? ','.$type2 : '');
break;
case 'select-day':
$type = 1;
$type2 = 31;
$type3 = 1;
// fall-through
case 'select-number': // options: rows,min,max,decrement,suffix
$type = $type === '' ? 1 : intval($type); // min
$type2 = $type2 === '' ? 10 : intval($type2); // max
$format = '%d';
if (!empty($type3) && $type3[0] == '0') // leading zero
{
$format = '%0'.(intval($type3) < 10 ? strlen($type3): strlen($type3) - 1).'d';
}
$type3 = !$type3 ? 1 : intval($type3); // decrement
if (($type <= $type2) != ($type3 > 0))
{
$type3 = -$type3; // void infinite loop
}
if (!empty($type4)) $format .= lang($type4);
for ($i=0,$n=$type; $n <= $type2 && $i <= 100; $n += $type3,++$i)
{
$cell['sel_options'][$n] = sprintf($format,$n);
}
$cell['no_lang'] = True;
$cell['enhance'] = false;
break;
case 'select-hour':
for ($h = 0; $h <= 23; ++$h)
{
$cell['sel_options'][$h] = $GLOBALS['egw_info']['user']['preferences']['common']['timeformat'] == 12 ?
(($h % 12 ? $h % 12 : 12).' '.($h < 12 ? lang('am') : lang('pm'))) :
sprintf('%02d',$h);
}
$cell['no_lang'] = True;
$cell['enhance'] = false;
break;
case 'select-app': // type2: 'user'=apps of current user, 'enabled', 'installed' (default), 'all' = not installed ones too
$apps = array();
foreach ($GLOBALS['egw_info']['apps'] as $app => $data)
{
if ($type2 == 'enabled' && (!$data['enabled'] || !$data['status'] || $data['status'] == 3))
{
continue; // app not enabled (user can not have run rights for these apps)
}
if ($type2 != 'user' || $GLOBALS['egw_info']['user']['apps'][$app])
{
$apps[$app] = lang($app);
}
}
if ($type2 == 'all')
{
$dir = opendir(EGW_SERVER_ROOT);
while ($file = readdir($dir))
{
if (@is_dir(EGW_SERVER_ROOT."/$file/setup") && $file[0] != '.' &&
!isset($apps[$app = basename($file)]))
{
$apps[$app] = $app . ' (*)';
}
}
closedir($dir);
}
natcasesort($apps);
$cell['sel_options'] = is_array($cell['sel_options']) ? $cell['sel_options']+$apps : $apps;
break;
case 'select-lang':
$cell['sel_options'] = translation::list_langs();
$cell['no_lang'] = True;
break;
case 'select-timezone': // options: #rows,$type
if (is_numeric($value))
{
$value = calendar_timezones::id2tz($value);
}
if ($readonly) // for readonly we dont need to fetch all TZ's
{
$cell['sel_options'][$value] = calendar_timezones::tz2id($value,'name');
}
else
{
$cell['sel_options'] = $type ? egw_time::getTimezones() : egw_time::getUserTimezones($value);
}
break;
}
if(!array_key_exists('enhance', $cell) && !is_null($enhance))
{
$cell['enhance'] = $enhance;
}
if ($rows > 1)
{
unset($cell['sel_options']['']);
}
return True; // extra Label Ok
}
/**
* internal function to format account-data
*/
function accountInfo($id,$acc=0,$longnames=0,$show_type=0)
{
if (!$id)
{
return '&nbsp;';
}
if (!is_array($acc))
{
$data = $GLOBALS['egw']->accounts->get_account_data($id);
if (!isset($data[$id])) return '#'.$id;
foreach(array('type','lid','firstname','lastname') as $name)
{
$acc['account_'.$name] = $data[$id][$name];
}
}
$info = $show_type ? '('.$acc['account_type'].') ' : '';
if ($acc['account_type'] == 'g')
{
$longnames = 1;
}
switch ($longnames)
{
case 2:
$info .= '&lt;'.$acc['account_lid'].'&gt; ';
// fall-through
case 1:
$info .= $acc['account_type'] == 'g' ? lang('group').' '.$acc['account_lid'] :
$acc['account_firstname'].' '.$acc['account_lastname'];
break;
case '0':
$info .= $acc['account_lid'];
break;
default: // use the phpgw default
$info = $GLOBALS['egw']->common->display_fullname($acc['account_lid'],
$acc['account_firstname'],$acc['account_lastname']);
break;
}
return $info;
}
/**
* postprocessing method, called after the submission of the form
*
* It has to copy the allowed/valid data from $value_in to $value, otherwise the widget
* will return no data (if it has a preprocessing method). The framework insures that
* the post-processing of all contained widget has been done before.
*
* @param string $name form-name of the widget
* @param mixed &$value the extension returns here it's input, if there's any
* @param mixed &$extension_data persistent storage between calls or pre- and post-process
* @param boolean &$loop can be set to true to request a re-submision of the form/dialog
* @param object &$tmpl the eTemplate the widget belongs too
* @param mixed &value_in the posted values (already striped of magic-quotes)
* @return boolean true if $value has valid content, on false no content will be returned!
*/
function post_process($name,&$value,&$extension_data,&$loop,&$tmpl,$value_in)
{
switch ($extension_data['type'])
{
case 'select-cat':
$value = $value_in;
// check if we have some unavailible cats and add them again
if (is_array($extension_data['unavailible']) && $extension_data['unavailible'])
{
if (is_array($value)) // multiselection
{
$value = array_merge($value,$extension_data['unavailible']);
}
elseif (!$value) // non-multiselection and nothing selected by the user
{
$value = $extension_data['unavailible'][0];
}
}
break;
case 'select-dow':
$value = 0;
if (!is_array($value_in)) $value_in = explode(',',$value_in);
foreach($value_in as $val)
{
$value |= $val;
}
//echo "<p>select_widget::post_process('$name',...,'$value_in'): value='$value'</p>\n";
break;
case 'select-country':
if ($extension_data['country_use_name'] && $value_in)
{
if (($value = $GLOBALS['egw']->country->get_full_name($value_in)))
{
break;
}
}
// fall through
default:
$value = $value_in;
break;
}
//echo "<p>select_widget::post_process('$name',,'$extension_data',,,'$value_in'): value='$value', is_null(value)=".(int)is_null($value)."</p>\n";
return true;
}
}

View File

@ -1,61 +0,0 @@
<?php
/**
* eGroupWare Baseclass for SiteMgr Modules written with eTemplate
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/
/**
* Baseclass for SiteMgr Modules written with eTemplate
*
* To create a SiteMgr module from an eTemplate app, you need to:
* - extend this class and set the $etemplate_method class-var to a method/menuaction of the app
* - the app need to return etemplate::exec (otherwise the content is empty)!!!
* - the app need to avoid redirects or links, as this would leave sitemgr!!!
*
* @package etemplate
* @subpackage api
* @author RalfBecker-AT-outdoor-training.de
* @license GPL
*/
class sitemgr_module extends Module // the Module class get automatic included by SiteMgr
{
/**
* @var string $etemplate_method Method/menuaction of an eTemplate app to be used as module
*/
var $etemplate_method;
/**
* generate the module content AND process submitted forms
*
* @param array &$arguments $arguments['arg1']-$arguments['arg3'] will be passed for non-submitted forms (first call)
* @param array $properties
* @return string the html content
*/
function get_content(&$arguments,$properties)
{
list($app) = explode('.',$this->etemplate_method);
$GLOBALS['egw']->translation->add_app($app);
$extra = "<style type=\"text/css\">\n<!--\n@import url(".$GLOBALS['egw_info']['server']['webserver_url'].
"/etemplate/templates/default/app.css);\n";
if ($app != 'etemplate' && file_exists(EGW_SERVER_ROOT.'/'.$app.'/templates/default/app.css'))
{
$extra .= "@import url(".$GLOBALS['egw_info']['server']['webserver_url'].
'/'.$app."/templates/default/app.css);\n";
}
$extra .= "-->\n</style>\n";
$extra .= '<script src="'.$GLOBALS['egw_info']['server']['webserver_url'].'/etemplate/js/etemplate.js" type="text/javascript"></script>'."\n";
$ret = false;
if($_POST['etemplate_exec_id'])
{
$ret = ExecMethod('etemplate.etemplate.process_exec');
}
return $extra.($ret ? $ret : ExecMethod2($this->etemplate_method,null,$arguments['arg1'],$arguments['arg2'],$arguments['arg3'],$arguments['arg4'],$arguments['arg5'],$arguments['arg6'],$arguments['arg7']));
}
}

View File

@ -1,32 +0,0 @@
<?php
/**
* EGroupware generalized SQL Storage Object
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @copyright 2002-16 by RalfBecker@outdoor-training.de
* @version $Id$
*/
use EGroupware\Api;
/**
* generalized SQL Storage Object
*
* the class can be used in following ways:
* 1) by calling the constructor with an app and table-name or
* 2) by setting the following documented class-vars in a class derived from this one
* Of cause you can derive from the class and call the constructor with params.
*
* @deprecated use Api\Storage\Base
*/
class so_sql extends Api\Storage\Base {}
/**
* Iterator applying a so_sql's db2data method on each element retrived
*
* @deprecated use Api\Storage\Db2DataIterator
*/
class so_sql_db2data_iterator extends Api\Storage\Db2DataIterator {}

View File

@ -1,30 +0,0 @@
<?php
/**
* EGroupware generalized SQL Storage Object Version 2
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @copyright 2002-16 by RalfBecker@outdoor-training.de
* @version $Id$
*/
use EGroupware\Api;
/**
* generalized SQL Storage Object
*
* the class can be used in following ways:
* 1) by calling the constructor with an app and table-name or
* 2) by setting the following documented class-vars in a class derifed from this one
* Of cause can you derife the class and call the constructor with params.
*
* The so_sql2 class uses a privat $data array and __get and __set methods to set its data.
* Please note:
* You have to explicitly declare other object-properties of derived classes, which should NOT
* be handled by that mechanism!
*
* @deprecated use Api\Storage\Base
*/
class so_sql2 extends Api\Storage\Base2 {}

View File

@ -1,39 +0,0 @@
<?php
/**
* EGroupware generalized SQL Storage Object with build in custom field support
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @copyright 2009-16 by RalfBecker@outdoor-training.de
* @version $Id$
*/
use EGroupware\Api;
/**
* Generalized SQL Storage Object with build in custom field support
*
* This class allows to display, search, order and filter by custom fields simply by replacing so_sql
* by it and adding custom field widgets to the eTemplates of an applications.
* It's inspired by the code from Klaus Leithoff, which does the same thing limited to addressbook.
*
* The schema of the custom fields table should be like (the lenght of the cf name is nowhere enfored and
* varies throughout eGW from 40-255, the value column from varchar(255) to longtext!):
*
* 'egw_app_extra' => array(
* 'fd' => array(
* 'prefix_id' => array('type' => 'int','precision' => '4','nullable' => False),
* 'prefix_name' => array('type' => 'string','precision' => '64','nullable' => False),
* 'prefix_value' => array('type' => 'text'),
* ),
* 'pk' => array('prefix_id','prefix_name'),
* 'fk' => array(),
* 'ix' => array(),
* 'uc' => array()
* )
*
* @deprecated use Api\Storage
*/
class so_sql_cf extends Api\Storage {}

File diff suppressed because it is too large Load Diff

View File

@ -1,441 +0,0 @@
<?php
/**
* EGroupware - TranslationTools
*
* @link http://www.egroupware.org
* @author Miles Lott <milos(at)groupwhere.org>
* @author Ralf Becker <RalfBecker(at)outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage translationtools
* @version $Id$
*/
class solangfile
{
var $total;
var $debug = False;
var $langarray; // Currently loaded translations
// array of missing phrases.
var $missingarray;
var $src_file;
var $tgt_file;
var $loaded_apps = array(); // Loaded app langs
var $functions = array( // functions containing phrases to translate and param#
'lang' => array(1),
'create_input_box' => array(1,3),
'create_check_box' => array(1,3),
'create_select_box' => array(1,4),
'create_text_area' => array(1,5),
'create_notify' => array(1,5),
'create_password_box' => array(1,3)
);
var $files = array(
'config.tpl' => 'config',
'hook_admin.inc.php' => 'file_admin',
'hook_preferences.inc.php' => 'file_preferences',
'hook_settings.inc.php' => 'file',
'hook_sidebox_menu.inc.php' => 'file',
'hook_acl_manager.inc.php' => 'acl_manager'
);
/**
* Reference to global db-object
*
* @var egw_db
*/
var $db;
function __construct()
{
$this->db = $GLOBALS['egw']->db;
}
function fetch_keys($app,$arr)
{
if (!is_array($arr))
{
return;
}
foreach($arr as $key => $val)
{
$this->plist[$key] = $app;
}
}
function config_file($app,$fname)
{
//echo "<p>solangfile::config_file(app='$app',fname='$fname')</p>\n";
$lines = file($fname);
if ($app != 'setup')
{
$app = 'admin';
}
foreach($lines as $n => $line)
{
while (preg_match('/\{lang_([^}]+)\}(.*)/',$line,$found))
{
$lang = str_replace('_',' ',$found[1]);
$this->plist[$lang] = $app;
$line = $found[2];
}
}
}
function special_file($app,$fname,$langs_in)
{
//echo "<p>solangfile::special_file(app='$app',fname='$fname',langs_in='$langs_in')</p>\n";
$app_in = $app;
switch ($langs_in)
{
case 'config':
$this->config_file($app,$fname);
return;
case 'file_admin':
case 'file_preferences':
$app = substr($langs_in,5);
break;
case 'phpgwapi':
$app = 'common';
break;
}
$GLOBALS['file'] = $GLOBALS['settings'] = array();
unset($GLOBALS['acl_manager']);
ob_start(); // suppress all output
// call the hooks and not the files direct, as it works for both files and method hooks
switch(basename($fname))
{
case 'hook_settings.inc.php':
$settings = $GLOBALS['egw']->hooks->single('settings',$app_in,true);
if (!is_array($settings) || !$settings)
{
$settings =& $GLOBALS['settings']; // old method of setting GLOBALS[settings], instead returning the settings
unset($GLOBALS['settings']);
}
break;
case 'hook_admin.inc.php':
$GLOBALS['egw']->hooks->single('admin',$app_in,true);
break;
case 'hook_preferences.inc.php':
$GLOBALS['egw']->hooks->single('preferences',$app_in,true);
break;
case 'hook_acl_manager.inc.php':
$GLOBALS['egw']->hooks->single('acl_manager',$app_in,true);
break;
default:
include($fname);
break;
}
ob_end_clean();
if (isset($GLOBALS['acl_manager'])) // hook_acl_manager
{
foreach($GLOBALS['acl_manager'] as $app => $data)
{
foreach ($data as $item => $arr)
{
foreach ($arr as $key => $val)
{
switch ($key)
{
case 'name':
$this->plist[$val] = $app;
break;
case 'rights':
foreach($val as $lang => $right)
{
$this->plist[$lang] = $app;
}
break;
}
}
}
}
}
if (count($GLOBALS['file'])) // hook_{admin|preferences|sidebox_menu}
{
foreach ($GLOBALS['file'] as $lang => $link)
{
$this->plist[$lang] = $app;
}
}
foreach((array)$settings as $data)
{
foreach(array('label','help') as $key)
{
if (isset($data[$key]) && !empty($data[$key]))
{
// run_lang: NULL, true --> help + label, false --> help only, -1 => none
if (!isset($data['run_lang']) || !$data['run_lang'] && $key == 'help' || $data['run_lang'] != -1)
{
$this->plist[$data[$key]] = $app;
}
}
}
}
}
function parse_php_app($app,$fd)
{
$reg_expr = '/('.implode('|',array_keys($this->functions)).")[ \t]*\([ \t]*(.*)$/i";
define('SEP',filesystem_separator());
if (!($d=dir($fd))) return;
while ($fn=$d->read())
{
if (@is_dir($fd.$fn.SEP))
{
if (($fn!='.')&&($fn!='..')&&($fn!='CVS') && $fn != '.svn')
{
$this->parse_php_app($app,$fd.$fn.SEP);
}
if ($fn == 'inc')
{
// make sure all hooks get called, even if they dont exist as hooks
foreach($this->files as $f => $type)
{
if (substr($f,0,5) == 'hook_' && !file_exists($f = $fd.'inc/'.$f))
{
$this->special_file($app,$f,$this->files[$type]);
}
}
}
}
elseif (is_readable($fd.$fn))
{
if (isset($this->files[$fn]))
{
$this->special_file($app,$fd.$fn,$this->files[$fn]);
}
if (strpos($fn,'.php') === False && strpos($fn,'.js') === False)
{
continue;
}
$lines = file($fd.$fn);
foreach($lines as $n => $line)
{
//echo "line='$line', lines[1+$n]='".$lines[1+$n]."'<br>\n";
while (preg_match($reg_expr,$line,$parts))
{
//echo "***func='$parts[1]', rest='$parts[2]'<br>\n";
$args = $this->functions[$parts[1]];
$rest = $parts[2];
for($i = 1; $i <= $args[0]; ++$i)
{
$next = 1;
if (!$rest || empty($del) || strpos($rest,$del,1) === False)
{
$rest .= trim($lines[++$n]);
}
$del = $rest[0];
if ($del == '"' || $del == "'")
{
//echo "rest='$rest'<br>\n";
while (($next = strpos($rest,$del,$next)) !== False && $rest[$next-1] == '\\')
{
$rest = substr($rest,0,$next-1).substr($rest,$next);
}
if ($next === False)
{
break;
}
$phrase = str_replace('\\\\','\\',substr($rest,1,$next-1));
//echo "next2=$next, phrase='$phrase'<br>\n";
if ($args[0] == $i)
{
//if (!isset($this->plist[$phrase])) echo ">>>$phrase<<<<br>\n";
$this->plist[$phrase] = $app;
array_shift($args);
if (!count($args))
{
break; // no more args needed
}
}
$rest = substr($rest,$next+1);
}
if(!preg_match('/'."[ \t\n]*,[ \t\n]*(.*)$".'/',$rest,$parts))
{
break; // nothing found
}
$rest = $parts[1];
}
$line = $rest;
}
}
}
}
$d->close();
}
function missing_app($app,$userlang=en)
{
$cur_lang=$this->load_app($app,$userlang);
define('SEP',filesystem_separator());
$fd = EGW_SERVER_ROOT . SEP . $app . SEP;
$this->plist = array();
$this->parse_php_app($app == 'phpgwapi' ? 'common' : $app,$fd);
reset($this->plist);
return($this->plist);
}
/**
* loads all app phrases into langarray
*
* @param $lang user lang variable (defaults to en)
*/
function load_app($app,$userlang='en',$target=True)
{
define('SEP',filesystem_separator());
$langarray = array();
$fn = translation::get_lang_file($app,$userlang);
$fd = dirname($fn);
if (@is_writeable($fn) || is_writeable($fd))
{
$wr = True;
}
if (!$target) $this->src_apps = array();
$from = translation::charset($userlang);
$to = translation::charset();
//echo "<p>solangfile::load_app('$app','$userlang') converting from charset('$userlang')='$from' to '$to'</p>\n";
if (file_exists($fn))
{
if ($fp = @fopen($fn,'rb'))
{
while ($data = fgets($fp,8000))
{
list($message_id,$app_name,,$content) = explode("\t",$data);
if(!$message_id)
{
continue;
}
if (empty($app_name))
{
$app_name = $app; // fix missing app_name
}
//echo '<br>load_app(): adding phrase: $this->langarray["'.$message_id.'"]=' . trim($content)."' for $app_name";
$_mess_id = strtolower(trim($message_id));
$langarray[$_mess_id]['message_id'] = $_mess_id;
$app_name = trim($app_name);
$langarray[$_mess_id]['app_name'] = $app_name;
if (!$target)
{
$this->src_apps[$app_name] = $app_name;
}
$langarray[$_mess_id]['content'] =
translation::convert(trim($content),$from,$to);
}
fclose($fp);
}
}
if ($target)
{
$this->tgt_file = $fn;
}
else
{
$this->src_file = $fn;
}
// stuff class array listing apps that are included already
$this->loaded_apps[$userlang]['filename'] = $fn;
$this->loaded_apps[$userlang]['writeable'] = $wr;
if (!$target) ksort($this->src_apps);
if($this->debug) { _debug_array($langarray); }
@ksort($langarray);
return $langarray;
}
function write_file($app_name,$langarray,$userlang,$which='target')
{
$to = translation::charset($userlang);
$from = translation::charset();
//echo "<p>solangfile::write_file('$app_name',,'$userlang') converting from '$from' to charset('$userlang')='$to'</p>\n";
$fn = translation::get_lang_file($app_name,$userlang);
if (file_exists($fn))
{
$backup = $fn . '.old';
@unlink($backup);
@rename($fn,$backup);
}
$fp = fopen($fn,'wb');
while(list($mess_id,$data) = @each($langarray))
{
$data['content'] = translation::convert(trim($data['content']),$from,$to);
// dont write empty content
if (!empty($data['content']))
{
fwrite($fp,$mess_id . "\t" . $data['app_name'] . "\t" . $userlang . "\t" . $data['content'] . "\n");
}
}
fclose($fp);
translation::invalidate_lang_file($app_name, $userlang);
if ($which == 'source')
{
$this->src_file = $fn;
}
else
{
$this->tgt_file = $fn;
}
return $fn;
}
}
/*
* Helper functions for searching new phrases in sidebox, preferences or admin menus
*/
if (!function_exists('display_sidebox') && $_GET['menuaction'] == 'developer_tools.uilangfile.missingphrase')
{
function display_sidebox($appname,$menu_title,$file) // hook_sidebox_menu
{
if (!is_array($file)) return;
unset($file['_NewLine_']);
if (is_array($GLOBALS['file']))
{
$GLOBALS['file'] = $file;
}
else
{
$GLOBALS['file'] += $file;
}
}
}
if (!function_exists('display_section') && $_GET['menuaction'] == 'developer_tools.uilangfile.missingphrase')
{
function display_section($appname,$file,$file2='') // hook_preferences, hook_admin
{
if (is_array($file2))
{
$file = $file2;
}
if (!is_array($file)) return;
if (is_array($GLOBALS['file']))
{
$GLOBALS['file'] = $file;
}
else
{
$GLOBALS['file'] += $file;
}
}
}

View File

@ -1,254 +0,0 @@
<?php
/**
* eGroupWare - eTemplate Extension - Tab Widget
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage extensions
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/
/**
* eTemplate Extension: widget that shows one row of tabs and an other row with the eTemplate of the selected tab
*
* You can use etemplate::setElementAttributes($name, 'tabs', array $tabs) to define tabs on runtime.
* $tabs is an array containing an array for each tab with following (eT2 compatible) values:
* - 'label' label of tab
* - 'help' title/helptext of tab label
* - 'template' name of template
* - 'id' optional namespace for template (actually 1. grid in template)
*
* See the example in 'etemplate.tab_widget.test'
*
* This widget is independent of the UI as it only uses etemplate-widgets and has therefor no render-function
*/
class tab_widget
{
/**
* exported methods of this class
* @var array
*/
var $public_functions = array(
'pre_process' => True,
'post_process' => True,
'noReadonlysALL' => true, // mark extension as not to set readonly for $readonlys['__ALL__']
);
/**
* availible extensions and there names for the editor
* @var string
*/
var $human_name = 'Tabs'; // this is the name for the editor
/**
* pre-processing of the extension
*
* This function is called before the extension gets rendered
*
* @param string $form_name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param etemplate &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process($form_name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl)
{
//echo "<p>tab_widget::pre_process('$form_name',".array2string($value).','.array2string($readonlys).','.array2string($extension_data).")</p>\n";
if (!$cell['onchange']) // onchange allows to use the old behavior (submit for each new tab)
{
$dom_enabled = true;
}
if (strpos($cell_name=$tab_names=$cell['name'],'=') !== false)
{
list($cell_name,$tab_names) = explode('=',$cell['name']);
$cell['name'] = $cell_name;
}
$labels = $helps = $names = $templates = $ids = array();
if ($cell['tabs']) // set via etemplate::setElementAttribute()
{
foreach($cell['tabs'] as $tab)
{
$labels[] = $tab['label'];
$helps[] = $tab['help'];
$names[] = $tab['id'] ? $tab['id'] : $tab['template'];
if ($tab['template']) $templates[count($names)-1] = $tab['template'];
if ($tab['id']) $ids[count($names)-1] = $tab['id'];
}
}
else
{
$labels = explode('|',$cell['label']);
$helps = explode('|',$cell['help']);
$names = explode('|',$tab_names);
}
$short_names = array();
foreach($names as $name)
{
$nparts = explode('.', $name);
$short_names[] = array_pop($nparts);
}
// disable tab mentioned in readonlys
foreach(is_array($readonlys) ? $readonlys : array($readonlys => true) as $name => $disable)
{
if ($name && $disable && (($key = array_search($name, $names)) !== false ||
($key = array_search($name, $short_names)) !== false))
{
unset($names[$key]);
$names = array_values($names);
unset($short_names[$key]);
$short_names = array_values($short_names);
unset($helps[$key]);
$helps = array_values($helps);
unset($labels[$key]);
$labels = array_values($labels);
if ($templates)
{
unset($templates[$key]);
$templates = array_values($templates);
}
}
}
$tab_widget = new etemplate('etemplate.tab_widget');
$tab_widget->no_onclick = true;
if ($value && strpos($value,'.') === false)
{
$value = $tmpl->name . '.' . $value;
}
foreach($names as $k => $name)
{
if (strpos($name,'.') === false)
{
$name = $names[$k] = $tmpl->name . '.' . $name;
}
if ($value == $name)
{
$selected_tab = $name;
}
}
$all_names = implode('|',$names);
if (empty($selected_tab))
{
$value = $selected_tab = $names[0];
}
$extension_data = $value; // remember the active tab in the extension_data
foreach($names as $k => $name)
{
if (strpos($name,'.') === false)
{
$name = $names[$k] = $tmpl->name . '.' . $name;
}
$tcell = boetemplate::empty_cell();
if ($value == $name)
{
$tcell['span'] = ',etemplate_tab_active';
}
else
{
$tcell['span'] = ',etemplate_tab';
}
if ($dom_enabled)
{
$tcell['onclick'] = "activate_tab('$name','$all_names','$form_name');";
$tcell['id'] = $name.'-tab';
}
elseif ($value != $name)
{
$tcell['type'] = 'button';
$tcell['onchange'] = '1';
$tcell['name'] = $cell_name.'['.$name.']';
}
$tcell['label'] = '<div>'.lang($labels[$k]).'</div>';
$tcell['help'] = $helps[$k];
$tab_widget->set_cell_attribute('tabs',1+$k,$tcell);
}
$tab_widget->set_cell_attribute('tabs','type','hbox');
$tab_widget->set_cell_attribute('tabs','size',count($names));
$tab_widget->set_cell_attribute('tabs','name','');
if ($dom_enabled)
{
foreach($names as $n => $name)
{
$bcell = boetemplate::empty_cell('template',$name);
$bcell['obj'] = new etemplate(empty($templates[$n]) ? $name : $templates[$n],$tmpl->as_array());
// hack to set id / content attribute on first grid, as it's not supported on template itself
if (!empty($ids[$n]) && $bcell['obj']->children[0]['type'] == 'grid')
{
$bcell['obj']->children[0]['name'] = $ids[$n];
}
$tab_widget->set_cell_attribute('body',$n+1,$bcell);
}
$tab_widget->set_cell_attribute('body','type','deck');
$tab_widget->set_cell_attribute('body','size',count($names));
$tab_widget->set_cell_attribute('body','span',',tab_body');
$tab_widget->set_cell_attribute('body','name',$cell_name);
}
else
{
$stab = new etemplate($selected_tab,$tmpl->as_array());
$tab_widget->set_cell_attribute('body','type','template');
$tab_widget->set_cell_attribute('body','size',''); // the deck has a '1' there
$tab_widget->set_cell_attribute('body','obj',$stab);
}
$tab_widget->set_cell_attribute('body','name',$selected_tab);
$cell['type'] = 'template';
$cell['obj'] = &$tab_widget;
$cell['label'] = $cell['help'] = '';
return False; // NO extra Label
}
/**
* postprocessing method, called after the submission of the form
*
* It has to copy the allowed/valid data from $value_in to $value, otherwise the widget
* will return no data (if it has a preprocessing method). The framework insures that
* the post-processing of all contained widget has been done before.
*
* Only used by select-dow so far
*
* @param string $name form-name of the widget
* @param mixed &$value the extension returns here it's input, if there's any
* @param mixed &$extension_data persistent storage between calls or pre- and post-process
* @param boolean &$loop can be set to true to request a re-submision of the form/dialog
* @param object &$tmpl the eTemplate the widget belongs too
* @param mixed &value_in the posted values (already striped of magic-quotes)
* @return boolean true if $value has valid content, on false no content will be returned!
*/
function post_process($name,&$value,&$extension_data,&$loop,&$tmpl,$value_in)
{
//echo "<p>tab_widget::post_process($name): value_in = "; _debug_array($value_in);
if (is_array($value_in))
{
foreach ($value_in as $tab => $button_pressed)
{
if ($button_pressed)
{
$value = $tab;
$loop = True;
}
}
}
else
{
$value = $value_in;
}
// if value not set (other button pressed), set the value we remembered in the extension_data
if (!$value)
{
$value = $extension_data;
}
return True;
}
}

View File

@ -1,214 +0,0 @@
<?php
/**
* eGroupWare eTemplate Extension - Tree Widgets
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage extensions
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/
/**
* eTemplate Extension: tree widgets with predefined eGW specific content
*/
class tree_widget
{
/**
* exported methods of this class
* @var array
*/
var $public_functions = array(
'pre_process' => True,
'post_process' => True,
);
/**
* availible extensions and there names for the editor
* @var array
*/
var $human_name = array(
'tree' => 'Tree',
'tree-cat' => 'Category tree',
);
/**
* Constructor of the extension
*
* @param string $ui '' for html
*/
function __construct($ui)
{
$this->ui = $ui;
}
/**
* pre-processing of the extension
*
* This function is called before the extension gets rendered
*
* @param string $name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param etemplate &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process($name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl)
{
list($rows,$type,$type2,$type3) = explode(',',$cell['size']);
$extension_data['type'] = $cell['type'];
$extension_data['multiple'] = $rows;
$readonly = $cell['readonly'] || $readonlys;
switch ($cell['type'])
{
case 'tree-cat': // !$type == globals cats too, $type2: not used, $type3: application, if not current-app
if ($readonly) // for readonly we dont need to fetch all cat's, nor do we need to indent them by level
{
$cell['no_lang'] = True;
foreach(is_array($value) ? $value : (strpos($value,',') !== false ? explode(',',$value) : array($value)) as $id)
{
if ($id) $cell['sel_options'][$id] = stripslashes($GLOBALS['egw']->categories->id2name($id));
}
break;
}
if (!$type3 || $type3 === $GLOBALS['egw']->categories->app_name)
{
$categories =& $GLOBALS['egw']->categories;
}
else // we need to instanciate a new cat object for the correct application
{
$categories = new categories('',$type3);
}
$cat2path=array();
foreach((array)$categories->return_sorted_array(0,False,'','','',!$type) as $cat)
{
$s = stripslashes($cat['name']);
if ($cat['app_name'] == 'phpgw' || $cat['owner'] == '-1')
{
$s .= ' &#9830;';
}
$cat2path[$cat['id']] = $path = ($cat['parent'] ? $cat2path[$cat['parent']].'/' : '').(string)$cat['id'];
$cell['sel_options'][$path] = $s;
}
// change cat-ids to pathes and preserv unavailible cats (eg. private user-cats)
if ($value)
{
$pathes = $extension_data['unavailable'] = array();
foreach(is_array($value) ? $value : explode(',',$value) as $cat)
{
if (isset($cat2path[$cat]))
{
$pathes[] = $cat2path[$cat];
}
else
{
$extension_data['unavailable'][] = $cat;
}
}
$value = $rows ? $pathes : $pathes[0];
}
$cell['size'] = $rows.($type2 ? ','.$type2 : '');
$cell['no_lang'] = True;
break;
}
// creating a div-id and var-name for the tree-object by replacing brackets with underscores and removing exec or evtl. cont parts
$tree_id = str_replace(array('exec[cont][','exec[','[',']'),array('','','_',''),$name);
$onNodeSelect = 'onNodeSelect_'.$tree_id;
$script = html::input_hidden($name,$value,false)."<script type='text/javascript'>";
if (($onclick = $cell['onclick']))
{
if (strpos($onclick,'$') !== false || $onclick{0} == '@')
{
$onclick = $tmpl->expand_name($onclick,$c,$r,$content['.c'],$content['.row'],$content);
}
$onclick = $tmpl->js_pseudo_funcs($onclick,$tmpl->name_vars);
}
if ($rows >= 1) // multiselction with checkboxes --> use onNodeSelect to check the item
{
unset($cell['sel_options']['']);
$onCheck = 'onCheck_'.$tree_id;
$script .= "
function $onCheck(id) {
document.getElementsByName('$name')[0].value=$tree_id.getAllChecked();
$onclick;
}
function $onNodeSelect(id) {
$tree_id.setCheck(id,$tree_id.isItemChecked(id) ? 0 : 1);
$onCheck(id);
}
";
}
else // single selection
{
$script .= "
function $onNodeSelect(id) {
document.getElementsByName('$name')[0].value=id;
$onclick;
}
";
}
$script .= "</script>\n";
list(,$class) = explode(',',$cell['span']);
$value = $script.html::tree($tmpl->_sel_options($cell,$name),$value,false,$onNodeSelect,$tree_id,$class,'',$onCheck);
$cell = boetemplate::empty_cell('html',$cell['name']);
return True; // extra Label Ok
}
/**
* postprocessing method, called after the submission of the form
*
* It has to copy the allowed/valid data from $value_in to $value, otherwise the widget
* will return no data (if it has a preprocessing method). The framework insures that
* the post-processing of all contained widget has been done before.
*
* Only used by select-dow so far
*
* @param string $name form-name of the widget
* @param mixed &$value the extension returns here it's input, if there's any
* @param mixed &$extension_data persistent storage between calls or pre- and post-process
* @param boolean &$loop can be set to true to request a re-submision of the form/dialog
* @param object &$tmpl the eTemplate the widget belongs too
* @param mixed &value_in the posted values (already striped of magic-quotes)
* @return boolean true if $value has valid content, on false no content will be returned!
*/
function post_process($name,&$value,&$extension_data,&$loop,&$tmpl,$value_in)
{
//echo "value_in"; _debug_array($value_in);
if (!preg_match('/^[0-9\\/'.($extension_data['multiple']?',':'').']*$/',$value_in)) return false; // guard against xss and other malious content
$value = $extension_data['multiple'] ? explode(',',$value_in) : $value_in;
switch ($extension_data['type'])
{
case 'tree-cat':
if ($extension_data['multiple'])
{
foreach($value as $k => $path)
{
$parts = explode('/',$path);
$value[$k] = array_pop($parts);
}
if ($extension_data['unavailable'])
{
$value += $extension_data['unavailable'];
}
}
else
{
$parts = explode('/',$value);
$value = array_pop($parts);
}
}
//echo "value"; _debug_array($value);
return true;
}
}

View File

@ -1,775 +0,0 @@
<?php
/**
* eGroupWare - EditableTemplates - GTK User Interface
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/
include_once(EGW_INCLUDE_ROOT . '/etemplate/inc/class.boetemplate.inc.php');
/**
* @author ralfbecker
* creates dialogs / HTML-forms from eTemplate descriptions
*
* etemplate or uietemplate extends boetemplate, all vars and public functions are inherited
* $tmpl =& CreateObject('etemplate.etemplate','app.template.name');
* $tmpl->exec('app.class.callback',$content_to_show);
* This creates a form from the eTemplate 'app.template.name' and takes care that
* the method / public function 'callback' in (bo)class 'class' of 'app' gets called
* if the user submitts the form. Vor the complete param's see the description of exec.
* @param $debug enables debug messages: 0=no, 1=calls to show and process_show, 2=content of process_show
* @param 3=calls to show_cell OR template- or cell-type name
*/
class gtk_etemplate extends boetemplate
{
var $debug;//='etemplate.editor.edit'; // 1=calls to show and process_show, 2=content after process_show,
// 3=calls to show_cell and process_show_cell, or template-name or cell-type
var $no_result = array( // field-types which generate no direct result
'label' => True,
'hrule' => True,
'image' => True,
'raw' => True,
'template' => True
);
var $font_width=8;
/**
* constructor of etemplate class, reads an eTemplate if $name is given
*
* @param as soetemplate.read
*/
function etemplate($name='',$template='default',$lang='default',$group=0,$version='',$rows=2,$cols=2)
{
$this->public_functions += array(
'exec' => True,
);
$this->boetemplate();
if (!$this->read($name,$template,$lang,$group,$version))
{
$this->init($name,$template,$lang,$group,$version,$rows,$cols);
return False;
}
return True;
}
/**
* Generats a Dialog from an eTemplate - abstract the UI-layer
*
* This is the only function an application should use, all other are INTERNAL and
* do NOT abstract the UI-layer, because they return HTML.
* Generates a webpage with a form from the template and puts process_exec in the
* form as submit-url to call process_show for the template before it
* ExecuteMethod's the given $methode of the caller.
* @param $methode Methode (e.g. 'etemplate.editor.edit') to be called if form is submitted
* @param $content Array with content to fill the input-fields of template, eg. the text-field
* @param with name 'name' gets its content from $content['name']
* @param $sel_options Array or arrays with the options for each select-field, keys are the
* @param field-names, eg. array('name' => array(1 => 'one',2 => 'two')) set the
* @param options for field 'name'. ($content['options-name'] is possible too !!!)
* @param $readonlys Array with field-names as keys for fields with should be readonly
* @param (eg. to implement ACL grants on field-level or to remove buttons not applicable)
* @param $preserv Array with vars which should be transported to the $method-call (eg. an id) array('id' => $id) sets $_POST['id'] for the $method-call
* @return nothing
*/
function exec($method,$content,$sel_options='',$readonlys='',$preserv='')
{
if (!$sel_options)
{
$sel_options = array();
}
if (!$readonlys)
{
$readonlys = array();
}
if (!$preserv)
{
$preserv = array();
}
if (!class_exists('gtk')) // load the gtk extension
{
if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN')
{
dl('php_gtk.dll');
}
else
{
dl('php_gtk.so');
}
}
/*
* Create a new top-level window and connect the signals to the appropriate
* functions if the window not already exists.
*/
if (!$GLOBALS['egw_info']['etemplate']['window'])
{
$window = new GtkWindow();
$window->connect('destroy',array('etemplate','destroy'));
$window->connect('delete-event',array('etemplate','delete_event'));
$window->set_title('eGroupWareGTK: '.$GLOBALS['egw_info']['server']['site_title']);
$window->set_default_size(1024,600);
$GLOBALS['egw_info']['etemplate']['window'] = &$window;
}
else
{
$window = &$GLOBALS['egw_info']['etemplate']['window'];
}
$this->result = array('test' => 'test');
$table = &$this->show($this->result,$content,$sel_options,$readonlys);
$table->set_border_width(10);
$table->show();
$swindow = new GtkScrolledWindow(null,null);
$swindow->set_policy(GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
$swindow->add_with_viewport($table);
$swindow->show();
$window->add($swindow);
$window->show_all();
/* Run the main loop. */
Gtk::main();
$this->collect_results();
$swindow->hide();
$window->remove($swindow);
unset($swindow);
unset($this->widgets);
// set application name so that lang, etc. works
list($GLOBALS['egw_info']['flags']['currentapp']) = explode('.',$method);
ExecMethod($method,array_merge($this->result,$preserv));
}
/**
* this is only an empty function for the GTK ui
*
* @return the adjusted content (in the simplest case that would be $content)
*/
function process_show(&$content,$readonlys='')
{
}
/*
* Called when delete-event happens. Returns false to indicate that the event
* should proceed.
*/
function delete_event()
{
return false;
}
/*
* Called when the window is being destroyed: destroy the session
*/
function destroy()
{
Gtk::main_quit();
$GLOBALS['egw']->session->destroy($GLOBALS['egw_info']['user']['sessionid'],$GLOBALS['egw_info']['user']['kp3']);
$GLOBALS['egw_info']['flags']['nodisplay'] = True;
exit;
}
function button_clicked(&$var,$form_name)
{
echo "button '$form_name' pressed\n";
$var = 'pressed';
Gtk::main_quit();
}
function submit()
{
echo "OnChange --> submit\n";
Gtk::main_quit();
}
function collect_results()
{
for($i=0; isset($this->widgets[$i]); ++$i)
{
$set = &$this->widgets[$i];
$widget = &$set['widget'];
$val_is_set = False;
echo "$i: $set[name]/$set[type]/".Gtk::type_name($widget->get_type());
switch ($set['type'])
{
case 'button': // is set to 'pressed' or is '' (not unset !!!)
$val_is_set = ($val = $this->get_array($this->result,$set['name']));
break;
case 'int':
case 'float':
case 'text':
case 'textarea':
$val = $widget->get_chars(0,-1);
$val_is_set = True;
break;
case 'checkbox':
$val = $widget->get_active();
$val_is_set = True;
break;
case 'radio':
if ($widget->get_active())
{
$val = $set['set_val'];
$val_is_set = True;
}
break;
case 'select':
$entry = $widget->entry;
$selected = $entry->get_chars(0,-1);
$options = $set['set_val'];
reset($options);
while (list($key,$val) = each($options))
{
if ($val == $selected)
{
$val = $key;
$val_is_set = True;
break;
}
}
break;
case 'date':
}
echo $val_is_set && !$set['readonly'] ? " = '$val'\n" : " NOT SET\n";
$this->set_array($this->result,$set['name'],$val,$val_is_set && !$set['readonly']);
}
}
/**
* creates HTML from an eTemplate
*
* This is done by calling show_cell for each cell in the form. show_cell itself
* calls show recursivly for each included eTemplate.
* You can use it in the UI-layer of an app, just make shure to call process_show !!!
* This is intended as internal function and should NOT be called by new app's direct,
* as it deals with HTML and is so UI-dependent, use exec instead.
* @param $content array with content for the cells, keys are the names given in the cells/form elements
* @param $sel_options array with options for the selectboxes, keys are the name of the selectbox
* @param $readonlys array with names of cells/form-elements to be not allowed to change
* @param This is to facilitate complex ACL's which denies access on field-level !!!
* @param $cname basename of names for form-elements, means index in $_POST
* @param eg. $cname='cont', element-name = 'name' returned content in $_POST['cont']['name']
* @param $show_xxx row,col name/index for name expansion
* @return the generated HTML
*/
function show(&$result,$content,$sel_options='',$readonlys='',$cname='',$show_c=0,$show_row=0)
{
if (!$sel_options)
{
$sel_options = array();
}
if (!$readonlys)
{
$readonlys = array();
}
if ($this->debug >= 1 || $this->debug == $this->name && $this->name)
{
echo "<p>etemplate.show($this->name): $cname =\n"; _debug_array($content);
}
if (!is_array($content))
{
$content = array(); // happens if incl. template has no content
}
$content += array( // for var-expansion in names in show_cell
'.c' => $show_c,
'.col' => $this->num2chrs($show_c-1),
'.row' => $show_row
);
$table = new GtkTable($this->rows,$this->cols,False);
$table->set_row_spacings(2);
$table->set_col_spacings(5);
$table->show();
reset($this->data);
if (isset($this->data[0]))
{
list($nul,$width) = each($this->data);
}
else
{
$width = array();
}
for ($r = 0; $row = 1+$r /*list($row,$cols) = each($this->data)*/; ++$r)
{
$old_cols = $cols; $old_class = $class; $old_height = $height;
if (!(list($nul,$cols) = each($this->data))) // no further row
{
$cols = $old_cols; $class = $old_class; $height = $old_height;
list($nul,$cell) = each($cols); reset($cols);
if (!($this->autorepeat_idx($cols['A'],0,$r,$idx,$idx_cname) && $idx_cname) &&
!($this->autorepeat_idx($cols['B'],1,$r,$idx,$idx_cname) && $idx_cname) ||
!$this->isset_array($content,$idx))
{
break; // no auto-row-repeat
}
}
else
{
$height = $this->data[0]["h$row"];
list($class,$valign) = explode(',',$this->data[0]["c$row"]);
switch($valign)
{
case 'top':
$valign = 0.0;
break;
case 'bottom':
$valign = 1.0;
break;
default:
$valign = 0.5;
}
}
$row_data = array();
for ($c = 0; True /*list($col,$cell) = each($cols)*/; ++$c)
{
$old_cell = $cell;
if (!(list($nul,$cell) = each($cols))) // no further cols
{
$cell = $old_cell;
if (!$this->autorepeat_idx($cell,$c,$r,$idx,$idx_cname,True) ||
!$this->isset_array($content,$idx))
{
break; // no auto-col-repeat
}
}
$col = $this->num2chrs($c);
//$row_data[$col] = $this->show_cell($cell,$content,$sel_options,$readonlys,$cname,$c,$r,$span);
$widget = &$this->show_cell($cell,$content,$sel_options,$readonlys,$cname,$c,$r,$span,$result);
if (($colspan = $span == 'all' ? $this->cols-$c : 0+$span) < 1)
{
$colspan = 1;
}
if ($widget)
{
$widget->show();
if ($align = ($cell['align'] || $valign))
{
switch ($cell['align'])
{
case 'center':
$align = 0.5;
break;
case 'right':
$align = 1.0;
break;
default:
$align = 0.0;
}
$align = new GtkAlignment($align,$valign,$cell['type'] == 'hrule' ? 1.0 : 0.0,0.0);
$align->add($widget);
}
$table->attach($align ? $align : $widget, $c, $c+$colspan, $r, $r+1,GTK_FILL,GTK_FILL,0,0);
}
if ($row_data[$col] == '' && $this->rows == 1)
{
unset($row_data[$col]); // omit empty/disabled cells if only one row
continue;
}
if ($colspan > 1)
{
$row_data[".$col"] .= " COLSPAN=$colspan";
for ($i = 1; $i < $colspan; ++$i,++$c)
{
each($cols); // skip next cell(s)
}
}
elseif ($width[$col]) // width only once for a non colspan cell
{
$row_data[".$col"] .= ' WIDTH='.$width[$col];
$width[$col] = 0;
}
// $row_data[".$col"] .= $this->html->formatOptions($cell['align'],'ALIGN');
// $row_data[".$col"] .= $this->html->formatOptions($cell['span'],',CLASS');
}
$rows[$row] = $row_data;
// $rows[".$row"] .= $this->html->formatOptions($height,'HEIGHT');
list($cl) = explode(',',$class);
if ($cl == 'nmr')
{
$cl .= $nmr_alternate++ & 1; // alternate color
}
// $rows[".$row"] .= $this->html->formatOptions($cl,'CLASS');
// $rows[".$row"] .= $this->html->formatOptions($class,',VALIGN');
}
if (!$GLOBALS['egw_info']['etemplate']['styles_included'][$this->name])
{
// $style = $this->html->style($this->style);
$GLOBALS['egw_info']['etemplate']['styles_included'][$this->name] = True;
}
return $table;
}
function draw_image($area, $event, $pixbuf)
{
$pixbuf->render_to_drawable($area->window,
$area->style->fg_gc[GTK_STATE_NORMAL],
$event->area->x, $event->area->y,
$event->area->x, $event->area->y,
$event->area->width, $event->area->height,
GDK_RGB_DITHER_NORMAL,
$event->area->x, $event->area->y);
}
/**
* generates HTML for 1 input-field / cell
*
* calls show to generate included eTemplates. Again only an INTERMAL function.
* @param $cell array with data of the cell: name, type, ...
* @param for rest see show
* @return the generated HTML
*/
function show_cell($cell,$content,$sel_options,$readonlys,$cname,$show_c,$show_row,&$span,&$result)
{
if ($this->debug >= 3 || $this->debug == $cell['type'])
{
echo "<p>etemplate.show_cell($this->name,name='${cell['name']}',type='${cell['type']}',cname='$cname')</p>\n";
}
list($span) = explode(',',$cell['span']); // evtl. overriten later for type template
$name = $this->expand_name($cell['name'],$show_c,$show_row,$content['.c'],$content['.row'],$content);
// building the form-field-name depending on prefix $cname and possibl. Array-subscript in name
if (preg_match('/^([^[]*)(\\[.*\\])$/',$name,$regs)) // name contains array-index
{
$form_name = $cname == '' ? $name : $cname.'['.$regs[1].']'.$regs[2];
eval(str_replace(']',"']",str_replace('[',"['",'$value = $content['.$regs[1].']'.$regs[2].';')));
$org_name = substr($regs[2],1,-1);
eval(str_replace(']',"']",str_replace('[',"['",'$var = &$result['.$regs[1].']'.$regs[2].';')));
}
else
{
$form_name = $cname == '' ? $name : $cname.'['.$name.']';
$value = $content[$name];
$org_name = $name;
$var = &$result[$name];
}
$readonly = $cell['readonly'] || $readonlys[$name] || $readonlys['__ALL__'];
if ($cell['disabled'] || $cell['type'] == 'button' && $readonly)
{
if ($this->rows == 1) {
return ''; // if only one row omit cell
}
$cell = $this->empty_cell(); // show nothing
$value = '';
}
if ($cell['onchange']) // values != '1' can only set by a program (not in the editor so far)
{
$options .= ' onChange="'.($cell['onchange']=='1'?'this.form.submit();':$cell['onchange']).'"';
}
if (strlen($label = $cell['label']) > 1)
{
$label = lang($label);
}
list($left_label,$right_label) = explode('%s',$label);
//echo "show_cell: type='$cell[type]', name='$cell[name]'-->'$name', value='$value'\n";
$widget = False;
switch ($cell['type'])
{
case 'label': // size: [[b]old][[i]talic]
$value = strlen($value) > 1 && !$cell['no_lang'] ? lang($value) : $value;
//if ($value != '' && strstr($cell['size'],'b')) $value = $this->html->bold($value);
//if ($value != '' && strstr($cell['size'],'i')) $value = $this->html->italic($value);
$html .= $value;
if ($value)
{
$widget = new GtkLabel($value);
if ($cell['align'] != 'center')
{
$widget->set_justify($cell['align'] == 'right' ? GTK_JUSTIFY_RIGHT : GTK_JUSTIFY_LEFT);
}
}
break;
case 'raw':
//$html .= $value;
break;
case 'int': // size: [min][,[max][,len]]
case 'float':
list($min,$max,$cell['size']) = explode(',',$cell['size']);
if ($cell['size'] == '')
{
$cell['size'] = $cell['type'] == 'int' ? 5 : 8;
}
// fall-through
case 'text': // size: [length][,maxLength]
if ($readonly)
{
//$html .= $this->html->bold($value);
}
else
{
//$html .= $this->html->input($form_name,$value,'',$options.$this->html->formatOptions($cell['size'],'SIZE,MAXLENGTH'));
}
list($len,$max) = explode(',',$cell['size']);
$widget = new GtkEntry();
$widget->set_text($value);
if ($max)
{
$widget->set_max_length($max);
}
$widget->set_editable(!$readonly);
if ($len)
{
$widget->set_usize($len*$this->font_width,0);
}
break;
case 'textarea': // Multiline Text Input, size: [rows][,cols]
//$html .= $this->html->textarea($form_name,$value,$options.$this->html->formatOptions($cell['size'],'ROWS,COLS'));
$widget = new GtkText(null,null);
$widget->insert_text($value,strlen($value));
$widget->set_editable(!$readonly);
break;
/* case 'date':
if ($cell['size'] != '')
{
$date = preg_split('/[\\/.-]/',$value);
$mdy = preg_split('/[\\/.-]/',$cell['size']);
for ($value=array(),$n = 0; $n < 3; ++$n)
{
switch($mdy[$n])
{
case 'Y': $value[0] = $date[$n]; break;
case 'm': $value[1] = $date[$n]; break;
case 'd': $value[2] = $date[$n]; break;
}
}
}
else
{
$value = array(date('Y',$value),date('m',$value),date('d',$value));
}
if ($readonly)
{
$html .= $GLOBALS['egw']->common->dateformatorder($value[0],$value[1],$value[2]);
}
else
{
$html .= $this->sbox->getDate($name.'[Y]',$name.'[m]',$name.'[d]',$value,$options);
}
break;
*/ case 'checkbox':
if ($value)
{
$options .= ' CHECKED';
}
//$html .= $this->html->input($form_name,'1','CHECKBOX',$options);
$widget = new GtkCheckButton($right_label);
$right_label = '';
$widget->set_active($value);
break;
case 'radio': // size: value if checked
if ($value == $cell['size'])
{
$options .= ' CHECKED';
}
//$html .= $this->html->input($form_name,$cell['size'],'RADIO',$options);
if (isset($this->buttongroup[$form_name]))
{
$widget = new GtkRadioButton($this->buttongroup[$form_name],$right_label);
}
else
{
$this->buttongroup[$form_name] = $widget = new GtkRadioButton(null,$right_label);
}
$right_label = '';
$widget->set_active($value == $cell['size']);
break;
case 'button':
//$html .= $this->html->submit_button($form_name,$cell['label'],'',strlen($cell['label']) <= 1 || $cell['no_lang'],$options);
$widget = new GtkButton(strlen($cell['label']) > 1 ? lang($cell['label']) : $cell['label']);
$widget->connect_object('clicked', array('etemplate', 'button_clicked'),&$var,$form_name);
break;
case 'hrule':
//$html .= $this->html->hr($cell['size']);
$widget = new GtkHSeparator();
break;
case 'template': // size: index in content-array (if not full content is past further on)
if ($this->autorepeat_idx($cell,$show_c,$show_row,$idx,$idx_cname) || $cell['size'] != '')
{
if ($span == '' && isset($content[$idx]['span']))
{ // this allows a colspan in autorepeated cells like the editor
$span = explode(',',$content[$idx]['span']); $span = $span[0];
if ($span == 'all')
{
$span = 1 + $content['cols'] - $show_c;
}
}
$readonlys = $readonlys[$idx];
$content = $content[$idx];
$var = &$result[$idx];
if ($idx_cname != '')
{
$cname .= $cname == '' ? $idx_cname : "[$idx_cname]";
}
//echo "<p>show_cell-autorepeat($name,$show_c,$show_row,cname='$cname',idx='$idx',idx_cname='$idx_cname',span='$span'): readonlys[$idx] ="; _debug_array($readonlys);
}
else
{
$var = &$result;
}
if ($readonly)
{
$readonlys['__ALL__'] = True;
}
$templ = is_object($cell['name']) ? $cell['name'] : new etemplate($name);
$templ->widgets = &$this->widgets;
//$html .= $templ->show($content,$sel_options,$readonlys,$cname,$show_c,$show_row);
$widget = $templ->show($var,$content,$sel_options,$readonlys,$cname,$show_c,$show_row);
break;
case 'select': // size:[linesOnMultiselect]
if (isset($sel_options[$name]))
{
$sel_options = $sel_options[$name];
}
elseif (isset($sel_options[$org_name]))
{
$sel_options = $sel_options[$org_name];
} elseif (isset($content["options-$name"]))
{
$sel_options = $content["options-$name"];
}
//$html .= $this->sbox->getArrayItem($form_name.'[]',$value,$sel_options,$cell['no_lang'],$options,$cell['size']);
reset($sel_options);
for ($maxlen=0; list($key,$val) = each($sel_options); )
{
if (!$cell['no_lang'])
{
$sel_options[$key] = lang($val);
}
if (($len = strlen($sel_options[$key])) > $maxlen)
{
$maxlen = $len;
}
}
$widget = new GtkCombo();
$widget->set_popdown_strings($sel_options);
$entry = $widget->entry;
$entry->set_text($sel_options[$value]);
$entry->set_editable(False);
$entry->set_usize($maxlen*$this->font_width,0);
if ($cell['onchange'] == '1')
{
$entry->connect('changed',array('etemplate', 'submit'));
}
break;
/* case 'select-percent':
$html .= $this->sbox->getPercentage($form_name,$value,$options);
break;
case 'select-priority':
$html .= $this->sbox->getPriority($form_name,$value,$options);
break;
case 'select-access':
$html .= $this->sbox->getAccessList($form_name,$value,$options);
break;
case 'select-country':
$html .= $this->sbox->getCountry($form_name,$value,$options);
break;
case 'select-state':
$html .= $this->sbox->list_states($form_name,$value); // no helptext - old Function!!!
break;
case 'select-cat':
$html .= $this->sbox->getCategory($form_name.'[]',$value,$cell['size'] >= 0,
False,$cell['size'],$options);
break;
case 'select-account':
$type = substr(strstr($cell['size'],','),1);
if ($type == '')
{
$type = 'accounts'; // default is accounts
}
$html .= $this->sbox->getAccount($form_name.'[]',$value,2,$type,0+$cell['size'],$options);
break;
*/ case 'image':
if (!($path = $GLOBALS['egw']->common->image(substr($this->name,0,strpos($this->name,'.')),$cell['label'])))
$path = $cell['label']; // name may already contain absolut path
if (!isset($GLOBALS['egw_info']['etemplate']['pixbufs'][$path]))
{
$GLOBALS['egw_info']['etemplate']['pixbufs'][$path] = GdkPixbuf::new_from_file('../..'.$path);
}
$pixbuf = &$GLOBALS['egw_info']['etemplate']['pixbufs'][$path];
if ($pixbuf)
{
$widget = new GtkDrawingArea();
$widget->size($pixbuf->get_width(),$pixbuf->get_height());
$widget->connect('expose_event',array('etemplate','draw_image'),$pixbuf);
}
else
{
echo "Can't load image '$path'";
}
break;
default:
//$html .= '<i>unknown type</i>';
$widget = new GtkLabel('unknown type: '.$cell['type']);
$widget->set_justify(GTK_JUSTIFY_LEFT);
break;
}
if ($widget && !$readonly && !$this->no_result[$cell['type']])
{
$this->widgets[] = array(
'widget' => &$widget,
'type' => $cell['type'],
'set_val' => $cell['type'] == 'radio' ? $cell['size'] : $sel_options,
'name' => $form_name,
'readonly' => $readonly
);
}
if ($cell['type'] != 'button' && $cell['type'] != 'image' && ($left_label || $right_label))
{
if (!$widget && !$right_label)
{
$widget = new GtkLabel($left_label);
}
else
{
$hbox = new GtkHBox(False,5);
if ($left_label)
{
$left = new GtkLabel($left_label);
$left->show();
$hbox->add($left);
}
if ($widget)
{
$widget->show();
$hbox->add($widget);
}
if ($right_label)
{
$right = new GtkLabel($right_label);
$right->show();
$hbox->add($right);
}
}
}
if ($cell['help'] && $widget)
{
if (!$this->tooltips)
{
$this->tooltips = new GtkTooltips();
}
$this->tooltips->set_tip($widget,lang($cell['help']),$this->name.'/'.$form_name);
}
return $hbox ? $hbox : $widget;
}
};

View File

@ -1,642 +0,0 @@
<?php
/**
* EGroupware - TranslationTools
*
* @link http://www.egroupware.org
* @author Miles Lott <milos(at)groupwhere.org>
* @author Ralf Becker <RalfBecker(at)outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage translationtools
* @version $Id$
*/
class uilangfile
{
var $helpme;
var $public_functions = array(
'index' => True,
'edit' => True,
'create' => True,
'addphrase' => True,
'missingphrase'=> True,
'missingphrase2'=> True,
'download' => True
);
/**
* business object
*
* @var bolangfile
*/
var $bo;
/**
* Reference to global Template object
*
* @var Template
*/
var $template;
/**
* nextmatchs object
*
* @var nextmatches
*/
var $nextmatchs;
function __construct()
{
$this->template = $GLOBALS['egw']->template;
$this->template->egroupware_hack = False; // else the phrases got translated
$this->bo = new bolangfile();
$this->nextmatchs = new nextmatchs();
translation::add_app('developer_tools');
translation::add_app('common');
egw_framework::csp_script_src_attrs('unsafe-inline');
}
function addphrase()
{
$app_name = get_var('app_name',array('POST','GET'));
$sourcelang = get_var('sourcelang',array('POST','GET'));
$targetlang = get_var('targetlang',array('POST','GET'));
$entry = $_POST['entry'];
$this->bo->read_sessiondata();
if($_POST['add'] || $_POST['cancel'] || $_POST['more'])
{
if($_POST['add'] || $_POST['more'])
{
if (get_magic_quotes_gpc())
{
foreach(array('message_id','content','target') as $name)
{
$entry[$name] = stripslashes($entry[$name]);
}
}
$this->bo->addphrase($entry);
if ($sourcelang == $targetlang)
{
$this->bo->target_langarray = $this->bo->source_langarray;
}
$this->bo->save_sessiondata();
}
if (!$_POST['more'])
{
$GLOBALS['egw']->redirect_link('/index.php',array(
'menuaction' => 'etemplate.uilangfile.edit',
'app_name' => $app_name,
'sourcelang' => $sourcelang,
'targetlang' => $targetlang
));
}
}
$GLOBALS['egw_info']['flags']['app_header'] = $GLOBALS['egw_info']['apps'][$GLOBALS['egw_info']['flags']['currentapp']]['title'].
' - '.lang('Add new phrase');
common::egw_header();
echo parse_navbar();
$this->template->set_var('form_action',$GLOBALS['egw']->link('/index.php','menuaction=etemplate.uilangfile.addphrase'));
$this->template->set_var('sourcelang',$sourcelang);
$this->template->set_var('targetlang',$targetlang);
$this->template->set_var('app_name',$app_name);
$this->template->set_file(array('form' => 'addphrase.tpl'));
$this->template->set_var('message_id_field','<textarea rows="5" style="width: 100%;" name="entry[message_id]"></textarea>');
if ($app_name == 'api') $app_name = 'common';
$this->template->set_var('app_field',$this->lang_option($app_name,isset($entry)?$entry['app_name']:$app_name,'entry[app_name]'));
$this->template->set_var('translation_field','<textarea rows="5" style="width: 100%;" name="entry[content]"></textarea>');
$this->template->set_var('target_field','<textarea rows="5" style="width: 100%;" name="entry[target]"></textarea>');
$this->template->set_var('lang_message_id',lang('message_id in English'));
$this->template->set_var('lang_app',lang('Application'));
$this->template->set_var('lang_translation',lang('Phrase in English (or empty if identical)'));
$this->template->set_var('lang_target',lang('Translation of phrase'));
$this->template->set_var('lang_add',lang('Add'));
$this->template->set_var('lang_more',lang('Add more'));
$this->template->set_var('lang_cancel',lang('Cancel'));
$this->template->pfp('phpgw_body','form');
}
function missingphrase()
{
$app_name = get_var('app_name',array('POST','GET'));
$sourcelang = get_var('sourcelang',array('POST','GET'));
$targetlang = get_var('targetlang',array('POST','GET'));
$this->bo->read_sessiondata();
$this->bo->missing_app($app_name,$sourcelang);
$this->bo->save_sessiondata();
// we have to redirect here, as solangfile defines function sidebox_menu, which clashes with the iDots func.
//
$GLOBALS['egw']->redirect_link('/index.php',array(
'menuaction' => 'etemplate.uilangfile.missingphrase2',
'app_name' => $app_name,
'sourcelang' => $sourcelang,
'targetlang' => $targetlang
));
}
function missingphrase2()
{
$app_name = get_var('app_name',array('POST','GET'));
$sourcelang = get_var('sourcelang',array('POST','GET'));
$targetlang = get_var('targetlang',array('POST','GET'));
$newlang = $_POST['newlang'];
$dlsource = $_POST['dlsource'];
$writesource = $_POST['writesource'];
$dltarget = $_POST['dltarget'];
$writetarget = $_POST['writetarget'];
$update = $_POST['update'];
$entry = $_POST['entry'];
$submit = $_POST['submit'];
$this->bo->read_sessiondata();
$this->template->set_file(array('langfile' => 'langmissing.tpl'));
$this->template->set_block('langfile','header','header');
$this->template->set_block('langfile','postheader','postheader');
$this->template->set_block('langfile','detail','detail');
$this->template->set_block('langfile','prefooter','prefooter');
$this->template->set_block('langfile','footer','footer');
if(!$sourcelang)
{
$sourcelang = 'en';
}
if(!$targetlang)
{
$targetlang = 'en';
}
$missingarray = $this->bo->missing_langarray;
//echo "missingarray=<pre>"; print_r($this->bo->missing_langarray); echo "</pre>\n";
if ($update)
{
$deleteme = $_POST['delete'];
//echo "deleteme=<pre>"; print_r($deleteme); echo "</pre>\n";
while (list($_mess,$_checked) = @each($deleteme))
{
if($_checked == 'on')
{
$_mess = $this->recode_id($_mess);
$this->bo->movephrase($_mess);
/* _debug_array($missingarray[$_mess]); */
unset($missingarray[$_mess]);
/* _debug_array($missingarray[$_mess]); */
}
}
unset($deleteme);
$this->bo->save_sessiondata();
$GLOBALS['egw']->redirect_link('/index.php',array(
'menuaction' => 'etemplate.uilangfile.edit',
'app_name' => $app_name,
'sourcelang' => $sourcelang,
'targetlang' => $targetlang
));
}
common::egw_header();
echo parse_navbar();
$this->template->set_var('lang_remove',lang('Add phrase'));
$this->template->set_var('lang_application',lang('Application'));
$this->template->set_var('lang_update',lang('Add'));
$this->template->set_var('lang_view',lang('Cancel'));
$this->template->set_var('action_url',$GLOBALS['egw']->link('/index.php','menuaction=etemplate.uilangfile.missingphrase2'));
$this->template->set_var('sourcelang',$sourcelang);
$this->template->set_var('targetlang',$targetlang);
$this->template->set_var('app_name',$app_name);
$this->template->set_var('app_title',$GLOBALS['egw_info']['apps'][$app_name]['title']);
$this->template->pfp('out','header');
if($sourcelang && $targetlang)
{
$this->template->set_var('lang_appname',lang('Application'));
$this->template->set_var('lang_message',lang('Message'));
$this->template->set_var('lang_original',lang('Original'));
$this->template->set_var('view_link',
$GLOBALS['egw']->link(
'/index.php',
'menuaction=etemplate.uilangfile.edit&app_name='.$app_name.'&sourcelang=' . $sourcelang . '&targetlang=' . $targetlang
)
);
$this->template->pfp('out','postheader');
while(list($key,$data) = @each($missingarray))
{
$mess_id = $this->encode_id($key);
$this->template->set_var('mess_id',$mess_id);
$this->template->set_var('source_content',html::htmlspecialchars($data['content']));
$this->template->set_var('transapp',$this->lang_option($app_name,$data['app_name'],"transapp[$mess_id]"));
$this->template->set_var('tr_class',$this->nextmatchs->alternate_row_color('',true));
$this->template->pfp('out','detail');
}
$this->template->pfp('out','prefooter');
$this->template->pfp('out','footer');
}
/* _debug_array($this->bo->loaded_apps); */
$this->bo->save_sessiondata();
}
function edit()
{
if ($_POST['cancel'])
{
$GLOBALS['egw']->redirect_link('/index.php','menuaction=etemplate.uilangfile.index');
}
$app_name = get_var('app_name',array('POST','GET'));
$sourcelang = get_var('sourcelang',array('POST','GET'));
$targetlang = get_var('targetlang',array('POST','GET'));
$entry = $_POST['entry'];
if($_POST['addphrase'] || $_POST['missingphrase'])
{
$GLOBALS['egw']->redirect_link('/index.php',array(
'menuaction' => 'etemplate.uilangfile.'.($_POST['addphrase']?'addphrase':'missingphrase'),
'app_name' => $app_name,
'sourcelang' => $sourcelang,
'targetlang' => $targetlang
));
}
if ($_POST['revert'])
{
$this->bo->clear_sessiondata();
}
$this->bo->read_sessiondata();
if($_POST['dlsource'])
{
$this->download('source',$sourcelang);
}
if($_POST['dltarget'])
{
$this->download('target',$targetlang);
}
$GLOBALS['egw_info']['flags']['css'] .= ".untranslated { background-color: #dab0b0; }\n";
common::egw_header();
echo parse_navbar();
$this->template->set_file(array('langfile' => 'langfile.tpl'));
$this->template->set_block('langfile','header','header');
$this->template->set_block('langfile','postheader','postheader');
$this->template->set_block('langfile','detail','detail');
$this->template->set_block('langfile','detail_long','detail_long');
$this->template->set_block('langfile','footer','footer');
$this->template->set_var('action_url',$GLOBALS['egw']->link('/index.php','menuaction=etemplate.uilangfile.edit'));
$this->template->set_var('lang_remove',lang('Remove'));
$this->template->set_var('lang_application',lang('Application'));
$this->template->set_var('lang_source',lang('Source Language'));
$this->template->set_var('lang_target',lang('Target Language'));
$this->template->set_var('lang_submit',lang('Load'));
$this->template->set_var('lang_update',lang('Save'));
$this->template->set_var('lang_revert',lang('Revert'));
$this->template->set_var('lang_cancel',lang('Cancel'));
$this->template->set_var('lang_step',lang('Step'));
$help = 'onMouseOver="self.status=\'%s\'; return true;" onMouseOut="self.status=\'\'; return true;"';
$this->template->set_var('cancel_help',sprintf($help,str_replace("'","\\'",lang('Returns to the application list, not saved changes get lost !!!'))));
$this->template->set_var('load_help',sprintf($help,str_replace("'","\\'",lang('Loads the selected lang-files, to be modified in the next steps'))));
$this->template->set_var('update_help',sprintf($help,str_replace("'","\\'",lang('Saves the added/changed translations to an internal buffer, to be used in further steps'))));
$this->template->set_var('search_help',sprintf($help,str_replace("'","\\'",lang('Searches the source-code for phrases not in the actual source-lang-file'))));
$this->template->set_var('add_help',sprintf($help,str_replace("'","\\'",lang('Allows you to add a single phrase'))));
$this->template->set_var('revert_help',sprintf($help,str_replace("'","\\'",lang('Clears the internal buffer, all changes made sofar are lost'))));
$this->template->set_var('download_help',sprintf($help,str_replace("'","\\'",lang('Download the lang-file to be saved in the apps setup-dir'))));
$this->template->set_var('write_help',sprintf($help,str_replace("'","\\'",lang('Write the lang-file to the apps setup-dir'))));
if(!$sourcelang)
{
$sourcelang = 'en';
}
if(!$targetlang)
{
$targetlang = $GLOBALS['egw_info']['user']['preferences']['common']['lang'];
}
foreach(translation::list_langs() as $lang_id => $lang_name)
{
$sourcelangs .= ' <option value="' . $lang_id . '"';
if ($lang_id == $sourcelang || !$sourcelang && $lang_id == 'en')
{
$sourcelangs .= ' selected="selected"';
}
$sourcelangs .= '>' . $lang_name . '</option>' . "\n";
$targetlangs .= ' <option value="' . $lang_id . '"';
if ($lang_id == $targetlang || !$targetlang && $lang_id == 'en')
{
$targetlangs .= ' selected="selected"';
}
$targetlangs .= '>' . $lang_name . '</option>' . "\n";
}
$this->template->set_var('sourcelangs',$sourcelangs);
$this->template->set_var('targetlangs',$targetlangs);
$this->template->set_var('app_name',$app_name);
$this->template->set_var('app_title',$GLOBALS['egw_info']['apps'][$app_name]['title']);
$this->template->pfp('out','header');
foreach($GLOBALS['egw_info']['apps']+array('setup' => array('title' => lang('Setup'))) as $app => $data)
{
$userapps .= '<option value="' . $userapp . '"';
if ($application_name == $userapp)
{
$userapps .= ' selected="selected"';
}
$userapps .= '>' . $data['title'] . '</option>' . "\n";
}
$this->template->set_var('userapps',$userapps);
if ($_POST['update'] || $_POST['update_too'])
{
$transapp = $_POST['transapp'];
$translations = $_POST['translations'];
$deleteme = $_POST['delete'];
foreach($transapp as $_mess => $_app)
{
if($_mess)
{
$_mess = strtolower(trim($this->recode_id($_mess)));
$this->bo->source_langarray[$_mess]['app_name'] = $_app;
$this->bo->target_langarray[$_mess]['app_name'] = $_app;
}
}
if (!is_array($this->bo->target_langarray))
{
$this->bo->target_langarray = array();
}
foreach($translations as $_mess => $_cont)
{
if($_mess && $_cont)
{
$_mess = strtolower(trim($this->recode_id($_mess)));
$this->bo->target_langarray[$_mess]['message_id'] = $_mess;
//POST method adds slashes if magic_quotes_gpc is set !!!
if (get_magic_quotes_gpc())
{
$_cont = stripslashes($_cont);
}
$this->bo->target_langarray[$_mess]['content'] = $_cont;
if($sourcelang == $targetlang)
{
$this->bo->source_langarray[$_mess]['content'] = $_cont;
}
}
}
if ($deleteme)
foreach($deleteme as $_mess => $_checked)
{
if($_checked == 'on')
{
$_mess = strtolower(trim($this->recode_id($_mess)));
unset($this->bo->source_langarray[$_mess]);
unset($this->bo->target_langarray[$_mess]);
}
}
@ksort($this->bo->source_langarray);
@ksort($this->bo->target_langarray);
/* $this->bo->save_sessiondata($this->bo->source_langarray,$this->bo->target_langarray); */
unset($transapp);
unset($translations);
if($deleteme)
{
$this->bo->save_sessiondata();
}
unset($deleteme);
}
if($_POST['writesource'] || $_POST['writesource_too'])
{
echo '<br>'.lang("Writing langfile for '%1' ...",$sourcelang);
$this->bo->write_file('source',$app_name,$sourcelang);
}
if($_POST['writetarget'] || $_POST['writetarget_too'])
{
echo '<br>'.lang("Writing langfile for '%1' ...",$targetlang);
$this->bo->write_file('target',$app_name,$targetlang);
}
if($sourcelang && $targetlang)
{
$this->template->set_var('lang_appname',lang('Application'));
$this->template->set_var('lang_message',lang('Message'));
$this->template->set_var('lang_original',lang('Original'));
$this->template->set_var('lang_translation',lang('Translation'));
$this->template->set_var('lang_missingphrase',lang('Search new phrases'));
$this->template->set_var('lang_addphrase',lang('Add new phrase'));
$this->template->set_var('sourcelang',$sourcelang);
$this->template->set_var('targetlang',$targetlang);
$this->template->pfp('out','postheader');
$langarray = $this->bo->add_app($app_name,$sourcelang);
$translation = $this->bo->load_app($app_name,$targetlang);
while(list($key,$data) = @each($langarray))
{
$mess_id = $this->encode_id($key);
$content = html::htmlspecialchars($mess_id == 'charset' ? $mess_id : $data['content']);
$transy = html::htmlspecialchars($translation[$key]['content']);
$this->template->set_var('mess_id',$mess_id);
$this->template->set_var('source_content',$content);
$this->template->set_var('content',$transy);
$this->template->set_var('transapp',$this->lang_option($app_name,$data['app_name'],"transapp[$mess_id]"));
$this->template->set_var('tr_class',empty($transy) ? 'untranslated' : $this->nextmatchs->alternate_row_color('',true));
if (($len = max(strlen($key),strlen($content))) > 50)
{
$this->template->set_var('rows',min(intval($len/80+0.5),10));
$this->template->pfp('out','detail_long');
}
else
{
$this->template->pfp('out','detail');
}
}
$this->template->set_var('sourcelang',$sourcelang);
$this->template->set_var('targetlang',$targetlang);
$this->template->set_var('lang_write',lang('Write'));
$this->template->set_var('lang_download',lang('Download'));
$this->template->set_var('src_file',$this->bo->src_file);
if(!$this->bo->loaded_apps[$sourcelang]['writeable'])
{
$this->template->set_block('footer','srcwrite','srcwrite');
$this->template->set_var('srcwrite','');
}
$this->template->set_var('tgt_file',$this->bo->tgt_file);
$this->template->set_var('targetlang',$targetlang);
if(!$this->bo->loaded_apps[$targetlang]['writeable'])
{
$this->template->set_block('footer','tgtwrite','tgtwrite');
$this->template->set_var('tgtwrite','');
}
$this->template->set_var('helpmsg',lang('you have to [Save] every manual change in the above fields, before you can go to the next step !!!'));
$this->template->pfp('out','footer');
}
/* _debug_array($this->bo->loaded_apps); */
$this->bo->save_sessiondata();
}
function encode_id($id)
{
return str_replace(array('[',']','&','"'),array('%5B','%5D','&amp;','&quot;'),$id);
}
function recode_id($id)
{
if (get_magic_quotes_gpc())
{
$id = stripslashes($id);
}
return str_replace(array('%5B','%5D'),array('[',']'),$id); // &amp; + &quot; are recode by php
}
function download($which,$userlang)
{
switch ($which)
{
case 'source':
$langarray = $this->bo->source_langarray;
break;
case 'target':
// removing phrases not in the source language
$langarray = $this->bo->target_langarray = array_intersect_assoc($this->bo->target_langarray,$this->bo->source_langarray);
break;
default:
break;
}
html::content_header(translation::LANGFILE_PREFIX . $userlang . '.lang');
$to = translation::charset($userlang);
$from = translation::charset();
while(list($mess_id,$data) = @each($langarray))
{
$content = translation::convert(trim($data['content']),$from,$to);
if (!empty($content))
{
echo $mess_id . "\t" . $data['app_name'] . "\t" . $userlang . "\t" . $content . "\n";
}
}
common::egw_exit();
}
function index()
{
$start = $_POST['start'];
$sort = $_POST['sort'];
$order = $_POST['order'];
$query = $_POST['query'];
$this->bo->save_sessiondata('','');
$GLOBALS['egw_info']['flags']['app_header'] = $GLOBALS['egw_info']['apps'][$GLOBALS['egw_info']['flags']['currentapp']]['title'].
' - '.lang('Installed applications');
common::egw_header();
echo parse_navbar();
$this->template->set_file(array('applications' => 'applications.tpl'));
$this->template->set_block('applications','list','list');
$this->template->set_block('applications','row','row');
$offset = $GLOBALS['egw_info']['user']['preferences']['common']['maxmatchs'];
$apps = array(
strtolower(lang('Setup')) => array(
'name' => 'setup',
'title' => lang('Setup')
)
);
foreach($GLOBALS['egw_info']['apps'] as $app => $data)
{
$apps[strtolower($data['title'])] = $data;
}
$total = count($apps);
if(!$sort)
{
$sort = 'ASC';
}
if($sort == 'ASC')
{
ksort($apps);
}
else
{
krsort($apps);
}
if ($start && $offset)
{
$limit = $start + $offset;
}
elseif ($start && !$offset)
{
$limit = $start;
}
elseif(!$start && !$offset)
{
$limit = $total;
}
else
{
$start = 0;
$limit = $offset;
}
if ($limit > $total)
{
$limit = $total;
}
$this->template->set_var('sort_title',$this->nextmatchs->show_sort_order($sort,'title','title','/index.php',lang('Title'),'&menuaction=etemplate.uilangfile.index'));
$this->template->set_var('lang_showing',$this->nextmatchs->show_hits($total,$start));
$this->template->set_var('left',$this->nextmatchs->left('/index.php',$start,$total,'&menuaction=etemplate.uilangfile.index'));
$this->template->set_var('right',$this->nextmatchs->right('/index.php',$start,$total,'&menuaction=etemplate.uilangfile.index'));
$this->template->set_var('lang_edit',lang('Edit'));
//$this->template->set_var('lang_translate',lang('Translate'));
$this->template->set_var('new_action',$GLOBALS['egw']->link('/index.php','menuaction=etemplate.uilangfile.create'));
$this->template->set_var('create_new',lang('Create New Language File'));
$i = 0;
foreach($apps as $data)
{
if($start <= $i && $i < $limit)
{
$this->template->set_var('tr_class',$this->nextmatchs->alternate_row_color('',true));
$this->template->set_var('name',$data['title']);
$this->template->set_var('edit','<a href="' . $GLOBALS['egw']->link('/index.php','menuaction=etemplate.uilangfile.edit&app_name=' . urlencode($data['name'])) . '"> ' . lang('Edit') . ' </a>');
// $this->template->set_var('translate','<a href="' . $GLOBALS['egw']->link('/index.php','menuaction=etemplate.uilangfile.translate&app_name=' . urlencode($app['name'])) . '"> ' . lang('Translate') . ' </a>');
$this->template->set_var('status',$status);
$this->template->parse('rows','row',True);
}
++$i;
}
$this->template->pparse('phpgw_body','list');
}
function lang_option($app_name,$current,$name)
{
$list = (is_array($this->bo->src_apps) ? $this->bo->src_apps : array()) + array(
$app_name => $app_name,
'common' => 'common',
'login' => 'login',
'admin' => 'admin',
'preferences' => 'preferences'
);
$select = "\n" .'<select name="' . $name . '">' . "\n";
foreach($list as $key => $val)
{
$select .= '<option value="' . $key . '"';
if ($key == $current && $current != '')
{
$select .= ' selected="selected"';
}
$select .= '>' . $val . '</option>'."\n";
}
$select .= '</select>'."\n";
return $select;
}
}

View File

@ -1,264 +0,0 @@
<?php
/**
* eGroupWare eTemplate Extension - URL widget: email addresses, external url's, clickable telephone numbers
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/
/**
* eGroupWare eTemplate Extension - URL widget: email addresses, external url's, clickable telephone numbers
*
* url:
* External URL with target _blank (http:// get's added, if there's no protocol)
* Uses our redirect.php script, if session is not stored in cookie!
*
* url-email:
* The value is an RFC822 email address or an interger account_id.
* If the value is empty or 0, the content of the options field is used instead.
* The address get displayed as name with the email as tooltip and a link to compose a mail.
*
* url-telefon:
* Displays a telephone number.
* If telephony integration is configured in addressbook, make the phone number a link to allow to call it.
* @todo Input validation and normalization of phone numbers
*/
class url_widget
{
/**
* exported methods of this class
*
* @var array
*/
var $public_functions = array(
'pre_process' => True,
);
/**
* availible extensions and there names for the editor
* @var string
*/
var $human_name = array(
'url' => 'Url',
'url-email' => 'EMail',
'url-phone' => 'Phone number',
);
/**
* Constructor of the extension
*
* @param string $ui '' for html
*/
function __construct($ui)
{
$this->ui = $ui;
}
/**
* pearl regular expression for email address
*
* has to be used case insensitive: /i
*/
//const EMAIL_PREG = '([a-z0-9][a-z0-9._-]*)?[a-z0-9]@([a-z0-9](|[a-z0-9_-]*[a-z0-9])\.)+[a-z]{2,6}';
//const EMAIL_PREG = '([a-z0-9][a-z0-9._\'\&\+-]*)?[a-z0-9_]@([a-z0-9ÄÖÜäöüß](|[a-z0-9ÄÖÜäöüß_-]*[a-z0-9ÄÖÜäöüß])\.)+[a-z]{2,6}';
const EMAIL_PREG = '^[^\x00-\x20()<>@,;:\\"\[\]]+@([a-z0-9ÄÖÜäöüß](|[a-z0-9ÄÖÜäöüß_-]*[a-z0-9ÄÖÜäöüß])\.)+[a-z]{2,}';
/**
* pre-processing of the extension
*
* This function is called before the extension gets rendered
*
* @param string $name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param object &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process($name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl)
{
$readonly = $cell['readonly'] || $readonlys;
switch($cell['type'])
{
case 'url-email': // size: size,max-size,{2=no validation,1=rfc822 name part allowed, default only email},default if value empty
list($size,$max_size,$validation_type,$default) = explode(',',$cell['size'],4); // 4 = allow default to contain commas
if (!$value) $value = $default; // use default from size/options if empty
$cell['no_lang'] = 1;
if (!$readonly)
{
$cell['type'] = 'text';
$cell['size'] = $size.','.$max_size.',';
if ((int)$validation_type < 2)
{
$cell['size'] .= $cell['needed'] ? '/^(' : '/^(|'; // if not needed allow empty, as EMAIL_PREG does not
$cell['size'] .= self::EMAIL_PREG;
if ($validation_type == 1) // allow rfc822 name part too: Ralf Becker <ralf@out.de>
{
$cell['size'] .= '|[^<]+ ?<'.self::EMAIL_PREG.'>';
}
//$cell['size'] .= ')$/iu,email';// ,email causes browser-side validation. browser is more restrictive, so we disable browserside validation
$cell['size'] .= ')$/iu';
}
#_debug_array($cell);
break;
}
$rfc822 = $value;
if (!(int)$size) $size = 22; // default size for display
if (is_numeric($value))
{
$email = $GLOBALS['egw']->accounts->id2name($value,'account_email');
$value = $GLOBALS['egw']->accounts->id2name($value,'account_fullname');
$rfc822 = $value.' <'.$email.'>';
}
elseif (preg_match('/^(.*) ?<(.*)>/',$value,$matches))
{
$value = $matches[1];
$email = $matches[2];
}
elseif (($at_pos = strpos($email=$value,'@')) !== false)
{
if (($amp_pos = strpos(substr($value,$at_pos),'&')) !== false)
{
//list($email,$addoptions) = explode('&',$value,2);
$email = substr($value,0,$amp_pos+$at_pos);
$addoptions = substr($value, $amp_pos+$at_pos+1);
//error_log(__METHOD__.__LINE__.$email.' '.$addoptions);
$rfc822 = $value = $email;
}
else
{
if (($q_pos = strpos(substr($value,$at_pos),'?')) !== false)
{
$email = substr($value,0,$q_pos+$at_pos);
$addoptions = substr($value, $q_pos+$at_pos+1);
$rfc822 = $value = $email;
}
}
if (strlen($value) > $size) // shorten the name to size-2 plus '...'
{
$value = substr($value,0,$size-2).'...';
}
}
$link = $this->email2link($email,$rfc822).($addoptions ? '&'.$addoptions : '');
$cell['type'] = 'label';
$cell['size'] = ','.$link.',,,,'.($link[0]=='f'?'700x750':'').($value != $email ? ','.$email : '');
break;
case 'url': // options: [size[,max-size[,preg]]]
list($size,$max_size,$preg) = explode(',',$cell['size'],3); // 3 = allow default to contain commas
if (!$readonly)
{
$cell['type'] = 'text';
$cell['size'] = "$size,$max_size,$preg"; // ,url"; not using html url type, as it requires a scheme
// todo: (optional) validation
break;
}
if (!(int)$size) $size = 24; // default size for display
$cell['type'] = 'label';
if ($value)
{
$link = (strpos($value,'://') === false) ? 'http://'.$value : $value;
$cell['size'] = ','.$link.',,,_blank';
}
if (substr($value,0,7) == 'http://')
{
$value = substr($value,7); // cut off http:// in display
}
if (strlen($value) > $size) // shorten the name to size-2 plus '...'
{
$value = substr($value,0,$size-2).'...';
}
break;
case 'url-phone': // options: [size[,max-size[,preg]]]
list($size,$max_size,$preg) = explode(',',$cell['size'],3); // 3 = allow default to contain commas
if (!$readonly)
{
$cell['type'] = 'text';
$cell['size'] = "$size,$max_size,$preg,tel";
// todo: (optional) validation
break;
}
$cell['type'] = 'label';
if ($value)
{
$link = self::phone2link($value);
$cell['size'] = ','.$link.($GLOBALS['egw_info']['server']['call_popup']=='none' ? '' : // 'none' = no target
',,,calling,'.$GLOBALS['egw_info']['server']['call_popup']);
}
break;
}
return True; // extra Label Ok
}
/**
* convert email-address in compose link
*
* @todo make the called link configurable in the user prefs, to eg. allow to allways use mailto ...
* @param string $email email-addresse
* @param string $rfc822 complete rfc822 addresse to use eg. for fmail
* @return array/string array with get-params or mailto:$email, or '' or no mail addresse
*/
static function email2link($email,$rfc822='')
{
if (!$email || strpos($email,'@') === false) return '';
if (!$GLOBALS['egw_info']['user']['preferences']['addressbook']['force_mailto'])
{
if($GLOBALS['egw_info']['user']['apps']['felamimail'])
{
//return 'felamimail.uicompose.compose&preset[to]='.($rfc822 ? $rfc822 : $email);
return 'felamimail.uicompose.compose&send_to='.base64_encode($rfc822 ? $rfc822 : $email);
}
if($GLOBALS['egw_info']['user']['apps']['email'])
{
return 'email.uicompose.compose&to='.$email;
}
}
return 'mailto:' . $email;
}
/**
* returns link to call the given phonenumber
*
* replaces '%1' with the phonenumber to call, '%u' with the user's account_lid and '%t' with his work-phone-number
*
* @param string $number phone number
* @return string|boolean string with link or false if no no telephony integration configured
*/
static function phone2link($number)
{
static $call_link;
if (is_null($call_link))
{
// for iPhone and Android: replace evtl. configured telephony integration link with tel: protocol
if (strpos($_SERVER['HTTP_USER_AGENT'],'AppleWebKit') !== false &&
(strpos($_SERVER['HTTP_USER_AGENT'],'iPhone') !== false || strpos($_SERVER['HTTP_USER_AGENT'],'Android') !== false))
{
$call_link = 'tel:%1';
}
else
{
$call_link = (string)$GLOBALS['egw_info']['server']['call_link'];
}
}
if (empty($number) || empty($call_link)) return false;
static $userphone;
if (is_null($userphone) && strpos($call_link,'%t') !== false)
{
$user = $GLOBALS['egw']->contacts->read('account:'.$GLOBALS['egw_info']['user']['account_id']);
$userphone = is_array($user) ? ($user['tel_work'] ? $user['tel_work'] : $user['tel_home']) : false;
}
$number = preg_replace('/[^0-9+]+/','',str_replace(array('&#9829;','(0)'),'',$number)); // remove number formatting chars messing up the links
return str_replace(array('%1','%u','%t'),array(urlencode($number),$GLOBALS['egw_info']['user']['account_lid'],$userphone),
$call_link);
}
}

View File

@ -1,561 +0,0 @@
<?php
/**
* eGroupWare eTemplate Extension - VFS Widgets
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @copyright 2008-10 by RalfBecker@outdoor-training.de
* @package etemplate
* @subpackage extensions
* @version $Id$
*/
/**
* eTemplate extension to display stuff from the VFS system
*
* Contains the following widgets:
* - vfs aka File name+link: clickable filename, with evtl. clickable path-components
* - vfs-name aka Filename: filename automatically urlencoded on return (urldecoded on display to user)
* - vfs-size aka File size: human readable filesize, eg. 1.4k
* - vfs-mode aka File mode: posix mode as string eg. drwxr-x---
* - vfs-mime aka File icon: mime type icon or thumbnail (if configured AND enabled in the user-prefs)
* - vfs-uid aka File owner: Owner of file, or 'root' if none
* - vfs-gid aka File group: Group of file, or 'root' if none
* - vfs-upload aka VFS file: displays either download and delete (x) links or a file upload
* + value is either a vfs path or colon separated $app:$id:$relative_path, eg: infolog:123:special/offer
* + if empty($id) / new entry, file is created in a hidden temporary directory in users home directory
* and calling app is responsible to move content of that dir to entry directory, after entry is saved
* + option: required mimetype or regular expression for mimetype to match, eg. '/^text\//i' for all text files
* + if path ends in a slash, multiple files can be uploaded, their original filename is kept then
*
* All widgets accept as value a full path.
* vfs-mime and vfs itself also allow an array with values like stat (incl. 'path'!) as value.
* vfs-mime also allows just the mime type as value.
* All other widgets allow additionally the nummeric value from the stat call (to not call it again).
*/
class vfs_widget
{
/**
* exported methods of this class
*
* @var array
*/
var $public_functions = array(
'pre_process' => True,
'post_process' => true, // post_process is only used for vfs-upload (all other widgets set $cell['readlonly']!)
);
/**
* availible extensions and there names for the editor
*
* @var array
*/
var $human_name = array(
'vfs' => 'File name+link', // clickable filename, with evtl. clickable path-components
'vfs-name' => 'File name', // filename automatically urlencoded
'vfs-size' => 'File size', // human readable filesize
'vfs-mode' => 'File mode', // posix mode as string eg. drwxr-x---
'vfs-mime' => 'File icon', // mime type icon or thumbnail
'vfs-uid' => 'File owner', // Owner of file, or 'root' if none
'vfs-gid' => 'File group', // Group of file, or 'root' if none
'vfs-upload' => 'VFS file', // displays either download and delete (x) links or a file upload
);
/**
* pre-processing of the extension
*
* This function is called before the extension gets rendered
*
* @param string $form_name form-name of the control
* @param mixed &$value value / existing content, can be modified
* @param array &$cell array with the widget, can be modified for ui-independent widgets
* @param array &$readonlys names of widgets as key, to be made readonly
* @param mixed &$extension_data data the extension can store persisten between pre- and post-process
* @param object &$tmpl reference to the template we belong too
* @return boolean true if extra label is allowed, false otherwise
*/
function pre_process($form_name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl)
{
//echo "<p>".__METHOD__."($form_name,$value,".array2string($cell).",...)</p>\n";
$type = $cell['type'];
if (!in_array($type,array('vfs-name','vfs-upload'))) $cell['readonly'] = true; // to not call post-process
// check if we have a path and not the raw value, in that case we have to do a stat first
if (in_array($type,array('vfs-size','vfs-mode','vfs-uid','vfs-gid')) && !is_numeric($value) || $type == 'vfs' && !$value)
{
if (!$value || !($stat = egw_vfs::stat($value)))
{
if ($value) $value = lang("File '%1' not found!",egw_vfs::decodePath($value));
$cell = boetemplate::empty_cell();
return true; // allow extra value;
}
}
$cell['type'] = 'label';
switch($type)
{
case 'vfs-upload': // option: required mimetype or regular expression for mimetype to match, eg. '/^text\//i' for all text files
if (empty($value) && preg_match('/^exec.*\[([^]]+)\]$/',$form_name,$matches)) // if no value via content array, use widget name
{
$value = $matches[1];
}
$extension_data = array('value' => $value, 'mimetype' => $cell['size'], 'type' => $type);
if ($value[0] != '/')
{
list($app,$id,$relpath) = explode(':',$value,3);
if (empty($id))
{
static $tmppath = array(); // static var, so all vfs-uploads get created in the same temporary dir
if (!isset($tmppath[$app])) $tmppath[$app] = '/home/'.$GLOBALS['egw_info']['user']['account_lid'].'/.'.$app.'_'.md5(time().session_id());
$value = $tmppath[$app];
unset($cell['onchange']); // no onchange, if we have to use a temporary dir
}
else
{
$value = egw_link::vfs_path($app,$id,'',true);
}
if (!empty($relpath)) $value .= '/'.$relpath;
}
$path = $extension_data['path'] = $value;
if (substr($path,-1) != '/' && self::file_exists($path) && !egw_vfs::is_dir($path)) // display download link and delete icon
{
$extension_data['path'] = $path;
$cell = $this->file_widget($value,$path,$cell['name'],$cell['label']);
}
else // file does NOT exists --> display file upload
{
$cell['type'] = 'file';
// if no explicit help message set and we only allow certain file types --> show them
if (empty($cell['help']) && $cell['size'])
{
if (($type = mime_magic::mime2ext($cell['size'])))
{
$type = '*.'.strtoupper($type);
}
else
{
$type = $cell['size'];
}
$cell['help'] = lang('Allowed file type: %1',$type);
}
}
// check if directory (trailing slash) is given --> upload of multiple files
if (substr($path,-1) == '/' && egw_vfs::file_exists($path) && ($files = egw_vfs::scandir($path)))
{
//echo $path; _debug_array($files);
$upload = $cell;
$cell = boetemplate::empty_cell('vbox','',array('size' => ',,0,0'));
$extension_data['files'] = $files;
$value = array();
foreach($files as $file)
{
$file = $path.$file;
$basename = basename($file);
unset($widget);
$widget = $this->file_widget($value[$basename],$file,$upload['name']."[$basename]");
boetemplate::add_child($cell,$widget);
}
boetemplate::add_child($cell,$upload);
}
break;
case 'vfs-size': // option: add size in bytes in brackets
$value = egw_vfs::hsize($size = is_numeric($value) ? $value : $stat['size']);
if ($cell['size']) $value .= ' ('.$size.')';
$cell['type'] = 'label';
break;
case 'vfs-mode':
$value = egw_vfs::int2mode(is_numeric($value) ? $value : $stat['mode']);
list($span,$class) = explode(',',$cell['span'],2);
$class .= ($class ? ' ' : '') . 'vfsMode';
$cell['span'] = $span.','.$class;
$cell['no_lang'] = true;
break;
case 'vfs-uid':
case 'vfs-gid':
$uid = !is_numeric($value) ? $stat[$type=='vfs-uid'?'uid':'gid'] : $value;
$value = !$uid ? 'root' : $GLOBALS['egw']->accounts->id2name($type=='vfs-uid'?$uid:-$uid); // our internal gid's are negative!
break;
case 'vfs':
if (is_array($value))
{
$name = $value['name'];
$path = substr($value['path'],0,-strlen($name)-1);
$mime = $value['mime'];
}
else
{
$name = $value;
$path = '';
$mime = egw_vfs::mime_content_type($value);
$value = array();
}
if (($cell_name = $cell['name']) == '$row')
{
$arr = explode('][',substr($form_name,0,-1));
$cell_name = array_pop($arr);
}
$cell['name'] = '';
$cell['type'] = 'hbox';
$cell['size'] = '0,,0,0';
foreach($name != '/' ? explode('/',$name) : array('') as $n => $component)
{
if ($n > (int)($path === '/'))
{
$sep = soetemplate::empty_cell('label','',array('label' => '/'));
soetemplate::add_child($cell,$sep);
unset($sep);
}
$value['c'.$n] = $component !== '' ? egw_vfs::decodePath($component) : '/';
$path .= ($path != '/' ? '/' : '').$component;
// replace id's in /apps again with human readable titles
$path_parts = explode('/',$path);
if ($path_parts[1] == 'apps')
{
switch(count($path_parts))
{
case 2:
$value['c'.$n] = lang('Applications');
break;
case 3:
$value['c'.$n] = lang($path_parts[2]);
break;
case 4:
if (is_numeric($value['c'.$n])) $value['c'.$n] .= egw_link::title($path_parts[2],$path_parts[3]);
break;
}
}
$popup = null;
if (egw_vfs::is_readable($path)) // show link only if we have access to the file or dir
{
if ($n < count($comps)-1 || $mime == egw_vfs::DIR_MIME_TYPE || egw_vfs::is_dir($path))
{
$value['l'.$n] = egw_link::mime_open($path, egw_vfs::DIR_MIME_TYPE, $popup);
$target = '';
}
else
{
$value['l'.$n] = egw_link::mime_open($path, $mime, $popup);
$target = '_blank';
}
}
if ($cell['onclick'])
{
$comp = boetemplate::empty_cell('button',$cell_name.'[c'.$n.']',array(
'size' => '1',
'no_lang' => true,
'span' => ',vfsFilename',
'label' => $value['c'.$n],
'onclick' => str_replace('$path',"'".addslashes($path)."'",$cell['onclick']),
));
}
else
{
$comp = boetemplate::empty_cell('label',$cell_name.'[c'.$n.']',array(
'size' => ',@'.$cell_name.'[l'.$n.'],,,'.$target.','.$popup,
'no_lang' => true,
'span' => ',vfsFilename',
));
}
boetemplate::add_child($cell,$comp);
unset($comp);
}
unset($cell['onclick']); // otherwise it's handled by the grid too
//_debug_array($comps); _debug_array($cell); _debug_array($value);
break;
case 'vfs-name': // size: [length][,maxLength[,allowPath]]
$cell['type'] = 'text';
list($length,$maxLength,$allowPath) = $options = explode(',',$cell['size']);
$preg = $allowPath ? '' : '/[^\\/]/'; // no slash '/' allowed, if not allowPath set
$cell['size'] = "$length,$maxLength,$preg";
$value = egw_vfs::decodePath($value);
$extension_data = array('type' => $type,'allowPath' => $allowPath);
break;
case 'vfs-mime': // size: [thsize] (thumbnail size)
//Read the thumbnail size
list($thsize) = explode(',', $cell['size']);
if (!is_numeric($thsize))
{
$thsize = NULL;
}
if (!$value)
{
$cell = boetemplate::empty_cell();
return true;
}
if (!is_array($value))
{
if ($value[0] == '/' || count(explode('/',$value)) != 2)
{
$mime = egw_vfs::mime_content_type($path=$value);
}
else
{
$mime = $value;
}
}
else
{
$path = $value['path'];
$mime = $value['mime'];
}
//error_log(__METHOD__."() type=vfs-mime: value=".array2string($value).": mime=$mime, path=$path");
$cell['type'] = 'image';
$cell['label'] = mime_magic::mime2label($mime);
list($mime_main,$mime_sub) = explode('/',$mime);
if ($mime_main == 'egw' || isset($GLOBALS['egw_info']['apps'][$mime_main]))
{
$value = $mime_main == 'egw' ? $mime_sub.'/navbar' : $mime; // egw-applications for link-widget
$cell['label'] = lang($mime_main == 'egw' ? $mime_sub : $mime_main);
list($span,$class) = explode(',',$cell['span'],2);
$class .= ($class ? ' ' : '') . 'vfsMimeIcon';
$cell['span'] = $span.','.$class;
}
elseif($path && $mime_main == 'image' && in_array($mime_sub,array('png','jpeg','jpg','gif','bmp')) &&
(string)$GLOBALS['egw_info']['server']['link_list_thumbnail'] != '0' &&
(string)$GLOBALS['egw_info']['user']['preferences']['common']['link_list_thumbnail'] != '0' &&
// check the size of the image, as too big images get no icon, but a PHP Fatal error: Allowed memory size exhausted
(!is_array($value) && ($stat = egw_vfs::stat($path)) ? $stat['size'] : $value['size']) < 1600000)
{
if (substr($path,0,6) == '/apps/')
{
$path = egw_vfs::parse_url(egw_vfs::resolve_url_symlinks($path),PHP_URL_PATH);
}
//Assemble the thumbnail parameters
$thparams = array('path' => $path);
if ($thsize)
{
$thparams['thsize'] = $thsize;
}
// add modification time to url to allow long caching
if (is_array($value) && $value['mtime'])
{
$thparams['mtime'] = $value['mtime'];
}
$value = $GLOBALS['egw']->link('/api/thumbnail.php', $thparams);
}
else
{
$value = egw_vfs::mime_icon($mime);
}
// mark symlinks (check if method exists, to allow etemplate to run on 1.6 API!)
if (method_exists('egw_vfs','is_link') && egw_vfs::is_link($path))
{
$broken = !egw_vfs::stat($path);
list($span,$class) = explode(',',$cell['span'],2);
$class .= ($class ? ' ' : '') . ($broken ? 'vfsIsBrokenLink' : 'vfsIsLink');
$cell['span'] = $span.','.$class;
$cell['label'] = ($broken ? lang('Broken link') : lang('Link')).': '.egw_vfs::decodePath(egw_vfs::readlink($path)).
(!$broken ? ' ('.$cell['label'].')' : '');
}
break;
default:
$value = 'Not yet implemented';
}
return true;
}
/**
* Create widget with download and delete (only if dir is writable) link
*
* @param mixed &$value
* @param string $path vfs path of download
* @param string $name name of widget
* @param string $label=null label, if not set basename($path) is used
* @return array
*/
static function file_widget(&$value,$path,$name,$label=null)
{
$value = empty($label) ? egw_vfs::decodePath(egw_vfs::basename($path)) : lang($label); // display (translated) Label or filename (if label empty)
$vfs_link = boetemplate::empty_cell('label',$name,array(
'size' => ','.egw_vfs::download_url($path).',,,_blank,,'.$path,
));
// if dir is writable, add delete link
if (egw_vfs::is_writable(egw_vfs::dirname($path)))
{
$cell = boetemplate::empty_cell('hbox','',array('size' => ',,0,0'));
boetemplate::add_child($cell,$vfs_link);
$delete_icon = boetemplate::empty_cell('button',$path,array(
'label' => 'delete',
'size' => 'delete', // icon
'onclick' => "return confirm('Delete this file');",
'span' => ',leftPad5',
));
boetemplate::add_child($cell,$delete_icon);
}
else
{
$cell = $vfs_link;
}
return $cell;
}
/**
* Check if vfs file exists *without* using the extension
*
* If you rename a file, you have to clear the cache ($clear_after=true)!
*
* @param string &$path on call path without extension, if existing on return full path incl. extension
* @param boolean $clear_after=null clear file-cache after (true) or before (false), default dont clear
* @return
*/
static function file_exists(&$path,$clear_after=null)
{
static $files = array(); // static var, to scan each directory only once
$dir = egw_vfs::dirname($path);
if ($clear_after === false) unset($files[$dir]);
if (!isset($files[$dir])) $files[$dir] = egw_vfs::file_exists($dir) ? egw_vfs::scandir($dir) : array();
$basename = egw_vfs::basename($path);
$basename_len = strlen($basename);
$found = false;
foreach($files[$dir] as $file)
{
if (substr($file,0,$basename_len) == $basename)
{
$path = $dir.'/'.$file;
$found = true;
}
}
if ($clear_after === true) unset($files[$dir]);
//echo "<p>".__METHOD__."($path) returning ".array2string($found)."</p>\n";
return $found;
}
/**
* postprocessing method, called after the submission of the form
*
* It has to copy the allowed/valid data from $value_in to $value, otherwise the widget
* will return no data (if it has a preprocessing method). The framework insures that
* the post-processing of all contained widget has been done before.
*
* Only used by vfs-upload so far
*
* @param string $name form-name of the widget
* @param mixed &$value the extension returns here it's input, if there's any
* @param mixed &$extension_data persistent storage between calls or pre- and post-process
* @param boolean &$loop can be set to true to request a re-submision of the form/dialog
* @param object &$tmpl the eTemplate the widget belongs too
* @param mixed &value_in the posted values (already striped of magic-quotes)
* @return boolean true if $value has valid content, on false no content will be returned!
*/
function post_process($name,&$value,&$extension_data,&$loop,&$tmpl,$value_in)
{
//error_log(__METHOD__."('$name',".array2string($value).','.array2string($extension_data).",$loop,,".array2string($value_in).')');
//echo '<p>'.__METHOD__."('$name',".array2string($value).','.array2string($extension_data).",$loop,,".array2string($value_in).")</p>\n";
if (!$extension_data) return false;
switch($extension_data['type'])
{
case 'vfs-name':
$value = $extension_data['allowPath'] ? egw_vfs::encodePath($value_in) : egw_vfs::encodePathComponent($value_in);
return true;
case 'vfs-upload':
break; // handeled below
default:
return false;
}
// from here on vfs-upload only!
// check if delete icon clicked
if ($_POST['submit_button'] == ($fname = str_replace($extension_data['value'],$extension_data['path'],$name)) ||
substr($extension_data['path'],-1) == '/' && substr($_POST['submit_button'],0,strlen($fname)-1) == substr($fname,0,-1))
{
if (substr($extension_data['path'],-1) == '/') // multiple files?
{
foreach($extension_data['files'] as $file) // check of each single file, to not allow deleting of arbitrary files
{
if ($_POST['submit_button'] == substr($fname,0,-1).$file.']')
{
if (!egw_vfs::unlink($extension_data['path'].$file))
{
etemplate::set_validation_error($name,lang('Error deleting %1!',egw_vfs::decodePath($extension_data['path'].$file)));
}
break;
}
}
}
elseif (!egw_vfs::unlink($extension_data['path']))
{
etemplate::set_validation_error($name,lang('Error deleting %1!',egw_vfs::decodePath($extension_data['path'])));
}
$loop = true;
return false;
}
// handle file upload
$name = preg_replace('/^exec\[([^]]+)\](.*)$/','\\1\\2',$name); // remove exec prefix
if (!is_array($_FILES['exec']) || !($filename = boetemplate::get_array($_FILES['exec']['name'],$name)))
{
return false; // no file attached
}
$tmp_name = boetemplate::get_array($_FILES['exec']['tmp_name'],$name);
$error = boetemplate::get_array($_FILES['exec']['error'],$name);
if ($error)
{
etemplate::set_validation_error($name,lang('Error uploading file!')."\n".
etemplate::max_upload_size_message());
$loop = true;
return false;
}
if (empty($tmp_name) || function_exists('is_uploaded_file') && !is_uploaded_file($tmp_name) || !file_exists($tmp_name))
{
return false;
}
// check if type matches required mime-type, if specified
if (!empty($extension_data['mimetype']))
{
$type = boetemplate::get_array($_FILES['exec']['type'],$name);
$is_preg = $extension_data['mimetype'][0] == '/';
if (!$is_preg && strcasecmp($extension_data['mimetype'],$type) || $is_preg && !preg_match($extension_data['mimetype'],$type))
{
etemplate::set_validation_error($name,lang('File is of wrong type (%1 != %2)!',$type,$extension_data['mimetype']));
return false;
}
}
$path = $extension_data['path'];
if (substr($path,-1) != '/')
{
// add extension to path
$parts = explode('.',$filename);
if (($extension = array_pop($parts)) && mime_magic::ext2mime($extension)) // really an extension --> add it to path
{
$path .= '.'.$extension;
}
}
else // multiple upload with dir given (trailing slash)
{
$path .= egw_vfs::encodePathComponent($filename);
}
if (!egw_vfs::file_exists($dir = egw_vfs::dirname($path)) && !egw_vfs::mkdir($dir,null,STREAM_MKDIR_RECURSIVE))
{
etemplate::set_validation_error($name,lang('Error create parent directory %1!',egw_vfs::decodePath($dir)));
return false;
}
if (!copy($tmp_name,egw_vfs::PREFIX.$path))
{
etemplate::set_validation_error($name,lang('Error copying uploaded file to vfs!'));
return false;
}
$value = $path; // return path of file, important if only a temporary location is used
return true;
}
}

View File

@ -1,602 +0,0 @@
<?php
/**
* eGroupWare - eTemplates - xml-tools - helper class to create xml-files
* Originaly from the phpGW XSLT API
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/
function var2xml($name, $data)
{
$doc = new xmltool('root','','');
return $doc->import_var($name,$data,True,True);
}
class xmltool
{
/* for root nodes */
var $xmlversion = '1.0';
var $doctype = Array();
/* shared */
var $node_type = '';
var $name = '';
var $data_type;
var $data;
/* for nodes */
var $attributes = Array();
var $comments = Array();
var $indentstring = "\t";
/* start the class as either a root or a node */
function xmltool ($node_type = 'root', $name='',$indentstring="\t")
{
$this->node_type = $node_type;
$this->indentstring = $indentstring;
if ($this->node_type == 'node')
{
if($name != '')
{
$this->name = $name;
}
else
{
echo 'You must name node type objects<br>';
exit;
}
}
}
function set_version ($version = '1.0')
{
$this->xmlversion = $version;
return True;
}
function set_doctype ($name, $uri = '')
{
if ($this->node_type == 'root')
{
$this->doctype[$name] = $uri;
return True;
}
else
{
return False;
}
}
function add_node ($node_object, $name = '')
{
switch ($this->node_type)
{
case 'root':
if (is_object($node_object))
{
$this->data = $node_object;
}
else
{
$this->data = $this->import_var($name, $node_object);
}
break;
case 'node':
if(!is_array($this->data))
{
$this->data = Array();
$this->data_type = 'node';
}
if (is_object($node_object))
{
if ($name != '')
{
$this->data[$name] = $node_object;
}
else
{
$this->data[] = $node_object;
}
}
else
{
$this->data[$name] = $this->import_var($name, $node_object);
}
return True;
break;
}
}
function get_node ($name = '') // what is that function doing: NOTHING !!!
{
switch ($this->data_type)
{
case 'root':
break;
case 'node':
break;
case 'object':
break;
}
}
function set_value ($string)
{
$this->data = $string;
$this->data_type = 'value';
return True;
}
function get_value ()
{
if($this->data_type == 'value')
{
return $this->data;
}
else
{
return False;
}
}
function set_attribute ($name, $value = '')
{
$this->attributes[$name] = $value;
return True;
}
function get_attribute ($name)
{
return $this->attributes[$name];
}
function get_attributes ()
{
return $this->attributes;
}
function add_comment ($comment)
{
$this->comments[] = $comment;
return True;
}
function import_var($name, $value,$is_root=False,$export_xml=False)
{
//echo "<p>import_var: this->indentstring='$this->indentstring'</p>\n";
$node = new xmltool('node',$name,$this->indentstring);
switch (gettype($value))
{
case 'string':
case 'integer':
case 'double':
case 'NULL':
$node->set_value($value);
break;
case 'boolean':
if($value == True)
{
$node->set_value('1');
}
else
{
$node->set_value('0');
}
break;
case 'array':
$new_index = False;
while (list ($idxkey, $idxval) = each ($value))
{
if(is_array($idxval))
{
while (list ($k, $i) = each ($idxval))
{
if (is_int($k))
{
$new_index = True;
}
}
}
}
reset($value);
while (list ($key, $val) = each ($value))
{
if($new_index)
{
$keyname = $name;
$nextkey = $key;
}
else
{
$keyname = $key;
$nextkey = $key;
}
switch (gettype($val))
{
case 'string':
case 'integer':
case 'double':
case 'NULL':
$subnode = new xmltool('node', $nextkey,$this->indentstring);
$subnode->set_value($val);
$node->add_node($subnode);
break;
case 'boolean':
$subnode = new xmltool('node', $nextkey,$this->indentstring);
if($val == True)
{
$subnode->set_value('1');
}
else
{
$subnode->set_value('0');
}
$node->add_node($subnode);
break;
case 'array':
if($new_index)
{
while (list ($subkey, $subval) = each ($val))
{
$node->add_node($this->import_var($nextkey, $subval));
}
}
else
{
$subnode = $this->import_var($nextkey, $val);
$node->add_node($subnode);
}
break;
case 'object':
$subnode = new xmltool('node', $nextkey,$this->indentstring);
$subnode->set_value('PHP_SERIALIZED_OBJECT&:'.serialize($val));
$node->add_node($subnode);
break;
case 'resource':
echo 'Halt: Cannot package PHP resource pointers into XML<br>';
exit;
default:
echo 'Halt: Invalid or unknown data type<br>';
exit;
}
}
break;
case 'object':
$node->set_value('PHP_SERIALIZED_OBJECT&:'.serialize($value));
break;
case 'resource':
echo 'Halt: Cannot package PHP resource pointers into XML<br>';
exit;
default:
echo 'Halt: Invalid or unknown data type<br>';
exit;
}
if($is_root)
{
$this->add_node($node);
if($export_xml)
{
$xml = $this->export_xml();
return $xml;
}
else
{
return True;
}
}
else
{
$this->add_node($node);
return $node;
}
}
function export_var()
{
if($this->node_type == 'root')
{
return $this->data->export_var();
}
if($this->data_type != 'node')
{
$found_at = strpos($this->data,'PHP_SERIALIZED_OBJECT&:');
if($found_at !== False)
{
return unserialize(str_replace ('PHP_SERIALIZED_OBJECT&:', '', $this->data));
}
return $this->data;
}
else
{
$new_index = False;
reset($this->data);
while(list($key,$val) = each($this->data))
{
if(!isset($found_keys[$val->name]))
{
$found_keys[$val->name] = True;
}
else
{
$new_index = True;
}
}
if($new_index)
{
reset($this->data);
while(list($key,$val) = each($this->data))
{
$return_array[$val->name][] = $val->export_var();
}
}
else
{
reset($this->data);
while(list($key,$val) = each($this->data))
{
$return_array[$val->name] = $val->export_var();
}
}
return $return_array;
}
}
function export_struct()
{
if($this->node_type == 'root')
{
return $this->data->export_struct();
}
$retval['tag'] = $this->name;
$retval['attributes'] = $this->attributes;
if($this->data_type != 'node')
{
$found_at = strpos($this->data,'PHP_SERIALIZED_OBJECT&:');
if($found_at !== False)
{
$retval['value'] = unserialize(str_replace ('PHP_SERIALIZED_OBJECT&:', '', $this->data));
}
else
{
$retval['value'] = $this->data;
}
return $retval;
}
else
{
reset($this->data);
while(list($key,$val) = each($this->data))
{
$retval['children'][] = $val->export_struct();
}
return $retval;
}
}
function import_xml_children($data, &$i, $parent_node)
{
while (++$i < count($data))
{
switch ($data[$i]['type'])
{
case 'cdata':
case 'complete':
$node = new xmltool('node',$data[$i]['tag'],$this->indentstring);
if(is_array($data[$i]['attributes']) && count($data[$i]['attributes']) > 0)
{
while(list($k,$v)=each($data[$i]['attributes']))
{
$node->set_attribute($k,$v);
}
}
$node->set_value($data[$i]['value']);
$parent_node->add_node($node);
break;
case 'open':
$node = new xmltool('node',$data[$i]['tag'],$this->indentstring);
if(is_array($data[$i]['attributes']) && count($data[$i]['attributes']) > 0)
{
while(list($k,$v)=each($data[$i]['attributes']))
{
$node->set_attribute($k,$v);
}
}
$node = $this->import_xml_children($data, $i, $node);
$parent_node->add_node($node);
break;
case 'close':
return $parent_node;
}
}
}
function import_xml($xmldata)
{
$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parse_into_struct($parser, $xmldata, $vals, $index);
xml_parser_free($parser);
unset($index);
$node = new xmltool('node',$vals[0]['tag'],$this->indentstring);
if(isset($vals[0]['attributes']))
{
while(list($key,$value) = each($vals[0]['attributes']))
{
$node->set_attribute($key, $value);
}
}
switch ($vals[0]['type'])
{
case 'complete':
$node->set_value($vals[0]['value']);
break;
case 'cdata':
$node->set_value($vals[0]['value']);
break;
case 'open':
$node = $this->import_xml_children($vals, $i = 0, $node);
break;
case 'closed':
exit;
}
$this->add_node($node);
}
function export_xml($indent = 1)
{
if ($this->node_type == 'root')
{
$result = '<?xml version="'.$this->xmlversion.'"?>'."\n";
if(count($this->doctype) == 1)
{
list($doctype_name,$doctype_uri) = each($this->doctype);
$result .= '<!DOCTYPE '.$doctype_name.' SYSTEM "'.$doctype_uri.'">'."\n";
}
if(count($this->comments) > 0 )
{
//reset($this->comments);
while(list($key,$val) = each ($this->comments))
{
$result .= "<!-- $val -->\n";
}
}
if(is_object($this->data))
{
$indent = 0;
$result .= $this->data->export_xml($indent);
}
return $result;
}
else /* For node objects */
{
for ($i = 0; $i < $indent; $i++)
{
$indentstring .= $this->indentstring;
}
$result = $indentstring.'<'.$this->name;
if(count($this->attributes) > 0 )
{
reset($this->attributes);
while(list($key,$val) = each ($this->attributes))
{
if (!is_array($val)) $result .= ' '.$key.'="'.htmlspecialchars($val,ENT_COMPAT,'utf-8').'"';
}
}
$endtag_indent = $indentstring;
if (empty($this->data_type))
{
$result .= '/>'."\n";
}
else
{
$result .= '>';
switch ($this->data_type)
{
case 'value':
if(is_array($this->data))
{
$type_error = True;
break;
}
/*if(preg_match("(&|<)", $this->data)) // this is unnecessary with htmlspecialchars($this->data)
{
$result .= '<![CDATA['.$this->data.']]>';
$endtag_indent = '';
}
else*/if(strlen($this->data) > 30 && !empty($this->indentstring))
{
$result .= "\n".$indentstring.$this->indentstring.htmlspecialchars($this->data,ENT_COMPAT,'utf-8')."\n";
$endtag_indent = $indentstring;
}
else
{
$result .= htmlspecialchars($this->data,ENT_COMPAT,'utf-8');
$endtag_indent = '';
}
break;
case 'node':
$result .= "\n";
if(!is_array($this->data))
{
$type_error = True;
break;
}
$subindent = $indent+1;
reset($this->data);
while(list($key,$val) = each ($this->data))
{
if(is_object($val))
{
$result .= $val->export_xml($subindent);
}
}
break;
default:
if($this->data != '')
{
echo 'Invalid or unset data type ('.$this->data_type.'). This should not be possible if using the class as intended<br>';
}
}
if ($type_error)
{
echo 'Invalid data type. Tagged as '.$this->data_type.' but data is '.gettype($this->data).'<br>';
}
$result .= $endtag_indent.'</'.$this->name.'>';
if($indent != 0)
{
$result .= "\n";
}
}
if(count($this->comments) > 0 )
{
reset($this->comments);
while(list($key,$val) = each ($this->comments))
{
$result .= $endtag_indent."<!-- $val -->\n";
}
}
return $result;
}
}
}
class xmlnode extends xmltool
{
function xmlnode($name)
{
$this->xmltool('node',$name);
}
}
class xmldoc extends xmltool
{
function xmldoc($version = '1.0')
{
$this->xmltool('root');
$this->set_version($version);
}
function add_root($root_node)
{
return $this->add_node($root_node);
}
}
?>

View File

@ -1,812 +0,0 @@
<?php
/**
* EGroupware - eTemplates - XUL/XML Import & Export
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @copyright 2002-11 by RalfBecker@outdoor-training.de
* @version $Id$
*/
if (!function_exists('var2xml'))
{
if (file_exists(EGW_API_INC.'class.xmltool.inc.php'))
{
include_once(EGW_API_INC.'class.xmltool.inc.php');
}
else
{
include_once('class.xmltool.inc.php');
}
}
/**
* XUL/XML Import & Export for eTemplates
*
* used only internaly
*/
class xul_io
{
/**
* translate attr, common to all widgets
*
* @var array
*/
var $attr2xul = array(
'name' => 'id',
'help' => 'statustext',
'span' => 'span,class',
'type' => '', // this is the widget-name => dont write as attr
'disabled' => 'disabled=true',
'readonly' => 'readonly=true',
'size' => 'options'
);
/**
* translate widget-names and widget-spec. attr., not set ones are identical
*
* @var array
*/
var $widget2xul = array(
'label' => array(
'.name' => 'description',
'label' => 'value',
'size' => 'font_style,href,activate_links,for,extra_link_target,extra_link_popup,extra_link_title',
),
'text' => array(
'.name' => 'textbox',
'size' => 'size,maxlength,validator'
),
'textarea' => array(
'.name' => 'textbox',
'.set' => 'multiline=true',
'size' => 'rows,cols'
),
'integer' => array(
'.name' => 'textbox',
'.set' => 'type=integer',
'size' => 'min,max,size,precision,step'
),
'int' => array(
'.name' => 'textbox',
'.set' => 'type=integer',
'size' => 'min,max,size,precision,step'
),
'float' => array(
'.name' => 'textbox',
'.set' => 'type=float',
'size' => 'min,max,size,precision,step'
),
'select' => array(
'.name' => 'menulist,menupopup',
),
'select-multi' => array( // multiselection, if size > 0
'.name' => 'listbox',
'size' => 'rows,options'
),
'template' => array(
'.name' => 'template',
'size' => 'content'
),
'image' => array(
'.name' => 'image',
'name' => 'src',
'size' => 'href,extra_link_target,imagemap,extra_link_popup,id',
),
'progres' => array(
'.name' => 'progress',
'size' => 'href,extra_link_target,,extra_link_popup',
),
'tab' => array(
'.name' => 'tabbox,tabs,tabpanels'
),
'button' => array(
'.name' => 'button',
'size' => 'image,ro_image'
),
'htmlarea' => array(
'size' => 'mode,height,width,expand_toolbar,base_href',
),
'nextmatch' => array(
'size' => 'template,hide_header,header_left,header_right',
),
);
/**
* translate xul-widget names to our internal ones, not set ones are identical
*
* @var array
*/
var $xul2widget = array(
'menulist' => 'select',
'listbox' => 'select',
'menupopup' => 'select',
'description' => 'label'
);
/**
* explicit whitelist for certain attributes and widget types
*/
var $attr_whitelist = array(
'rows' => array('textbox'),
'cols' => array('textbox'),
);
/**
* Keys of currently processed template on export, to resolve relative names
*
* @var array
*/
var $load_via;
/**
* sets an attribute in the xml object representing a widget
*
* @param object &$widget widget to set the attribute in
* @param string $attr comma delimited attr = default-value pairs, eg. "type=int,min=0"
* @param array $val array with values to set
*/
function set_attributes(&$widget,$attr,$val)
{
if ($attr != '' && !is_numeric($attr))
{
$attrs = explode(',',$attr);
if (count($attrs))
{
$vals = count($attrs) > 1 ? explode(',',$val,count($attrs)) : array($val);
foreach($attrs as $n => $attr)
{
if (($val = $vals[$n]) != '')
{
list($attr,$set) = explode('=',$attr);
$widget->set_attribute($attr,$set != '' ? $set : $val);
}
}
}
}
}
/**
* add a widget to a parent
*
* @param object &$parent parten to add the widget
* @param array $cell widget to add
* @param array &$embeded_too already embeded eTemplates
* @return object reference (!) the the xml object representing the widget, so other children can be added
*/
function &add_widget(&$parent,$cell,&$embeded_too)
{
// sort attributes, to stop xet files from changing because of changed attribute order
ksort($cell, SORT_STRING);
$type = $cell['type'];
if (is_array($type))
{
list(,$type) = each($type);
}
if (!$type) $cell['type'] = $type = 'unknown';
if (substr($type,0,6) == 'select')
{
$type = $cell['size'] > 1 ? 'select-multi' : 'select';
}
$widgetattr2xul = isset($this->widget2xul[$type]) ? $this->widget2xul[$type] : array();
$type = isset($widgetattr2xul['.name']) ? $widgetattr2xul['.name'] : $type;
list($type,$child,$child2) = explode(',',$type);
$widget = new xmlnode($type);
$attr_widget = &$widget;
if ($child)
{
$child = new xmlnode($child);
if ($type != 'tabbox') $attr_widget = &$child;
}
if ($child2)
{
$child2 = new xmlnode($child2);
}
if (isset($widgetattr2xul['.set'])) // set default-attr for type
{
$attrs = explode(',',$widgetattr2xul['.set']);
foreach($attrs as $attr)
{
list($attr,$val) = explode('=',$attr);
$widget->set_attribute($attr,$val);
}
}
switch ($type)
{
case 'nextmatch':
$tpls = $cell['size'] = explode(',', $cell['size']); // template,hide_header,header_left,header_right
unset($tpls[1]); // hide_header is no template
foreach($tpls as $n => $tpl)
{
if (empty($tpl)) continue;
$embeded = new boetemplate($tpl,$this->load_via);
if ($embeded_too)
{
$this->add_etempl($embeded,$embeded_too);
}
$cell['size'][$n] = $embeded->name;
unset($embeded);
}
$cell['size'] = implode(',', $cell['size']);
break;
case 'tabbox':
$labels = explode('|',$cell['label']); unset($cell['label']);
$helps = explode('|',$cell['help']); unset($cell['help']);
if (strpos($tab_names=$cell['name'],'=') !== false)
{
list($cell['name'],$tab_names) = explode('=',$cell['name']);
}
$names = explode('|',$tab_names);
for ($n = 0; $n < count($labels); ++$n)
{
$tab = new xmlnode('tab');
$tab->set_attribute('id',$names[$n]);
$tab->set_attribute('label',$labels[$n]);
if ($helps[$n]) $tab->set_attribute('statustext',$helps[$n]);
$child->add_node($tab);
$embeded = new boetemplate($names[$n],$this->load_via);
if ($embeded_too)
{
$this->add_etempl($embeded,$embeded_too);
}
$template = new xmlnode('template');
$template->set_attribute('id',$embeded->name);
$child2->add_node($template);
unset($embeded);
unset($template);
}
break;
case 'menulist': // id,options belongs to the 'menupopup' child
if ($cell['span'])
{
list($span, $class) = explode(',', $cell['span']);
if (!empty($span)) $this->set_attributes($widget, 'span', $span);
if (!empty($class))
{
$cell['span'] = ','.$class;
}
else
{
unset($cell['span']);
}
}
// fall-through
case 'listbox':
if ($cell['type'] != 'select') // one of the sub-types
{
$attr_widget->set_attribute('type',$cell['type']);
}
break;
case 'groupbox':
if ($cell['label'])
{
$caption = new xmlnode('caption');
$caption->set_attribute('label',$cell['label']);
$widget->add_node($caption);
unset($cell['label']);
}
// fall-through
case 'split':
case 'vbox':
case 'hbox':
case 'box':
case 'deck':
list($anz,$orient,$options) = explode(',',$cell['size'],3);
for ($n = 1; $n <= $anz; ++$n)
{
$this->add_widget($widget,$cell[$n],$embeded_too);
unset($cell[$n]);
}
// no sure where the data key gets set, but it gives a warning in xml serialization (empty array)
unset($cell['data']);
if (!empty($orient)) $cell['orient'] = $orient;
$cell['size'] = $options;
break;
case 'template':
if ($cell['name'][0] != '@' && $embeded_too)
{
$templ = new boetemplate();
if ($templ->read(boetemplate::expand_name($cell['name'],0,0),'default','default',0,'',$this->load_via))
{
$this->add_etempl($templ,$embeded_too);
}
unset($templ);
}
break;
case 'grid':
$this->add_grid($parent,$cell,$embeded_too);
return; // grid is already added
}
foreach($cell as $attr => $val)
{
if (is_array($val)) // correct old buggy etemplates
{
list(,$val) = each($val);
}
if (isset($widgetattr2xul[$attr]))
{
$attr = $widgetattr2xul[$attr];
}
elseif (isset($this->attr2xul[$attr]))
{
$attr = $this->attr2xul[$attr];
}
// check if attribute has an explicit whitelist and widget type is in it
if (isset($this->attr_whitelist[$attr]) && !in_array($type, $this->attr_whitelist[$attr]))
{
continue;
}
$this->set_attributes($attr_widget,$attr,$val);
}
if ($child)
{
$widget->add_node($child);
}
if ($child2)
{
$widget->add_node($child2);
}
$parent->add_node($widget);
}
/**
* add a grid to $parent (xml object)
*
* @param object &$parent where to add the grid
* @param array $grid grid to add
* @param array &embeded_too array with already embeded eTemplates
*/
function add_grid(&$parent,$grid,&$embeded_too)
{
$xul_grid = new xmlnode('grid');
$this->set_attributes($xul_grid,'width,height,border,class,spacing,padding,overflow',$grid['size']);
$this->set_attributes($xul_grid,'id',$grid['name']);
$xul_columns = new xmlnode('columns');
$xul_rows = new xmlnode('rows');
reset($grid['data']);
list(,$opts) = each ($grid['data']); // read over options-row
while (list($r,$row) = each ($grid['data']))
{
$xul_row = new xmlnode('row');
$this->set_attributes($xul_row,'class,valign',$opts["c$r"]);
$this->set_attributes($xul_row,'height,disabled,part',$opts["h$r"]);
$spanned = 0;
foreach($row as $c => $cell)
{
if ($r == '1') // write columns only once in the first row
{
$xul_column = new xmlnode('column');
$this->set_attributes($xul_column,'width,disabled',$opts[$c]);
$xul_columns->add_node($xul_column);
}
if ($spanned-- > 1)
{
continue; // spanned cells are not written
}
$this->add_widget($xul_row,$cell,$embeded_too);
$spanned = $cell['span'] == 'all' ? 999 : $cell['span'];
}
$xul_rows->add_node($xul_row);
}
$xul_grid->add_node($xul_columns);
$xul_grid->add_node($xul_rows);
$parent->add_node($xul_grid);
}
/**
* add / embed an eTemplate into the global $xul_overlay object (used by export)
*
* @param boetemplate &$etempl eTemplate to embed
* @param array &embeded_too array with already embeded templates
*/
function add_etempl(boetemplate $etempl,&$embeded_too)
{
if (is_array($embeded_too))
{
if (isset($embeded_too[$etempl->name]))
{
return; // allready embeded
}
}
else
{
$embeded_too = array();
}
$embeded_too[$etempl->name] = True;
$template = new xmlnode('template');
$template->set_attribute('id',$etempl->name);
$template->set_attribute('template',$etempl->template);
$template->set_attribute('lang',$etempl->lang);
$template->set_attribute('group',$etempl->group);
$template->set_attribute('version',$etempl->version);
$backup_load_via = $this->load_via;
$this->load_via = $etempl->as_array(-1);
foreach($etempl->children as $child)
{
$this->add_widget($template,$child,$embeded_too);
}
$this->load_via = $backup_load_via;
if ($etempl->style != '')
{
$styles = new xmlnode('styles');
$styles->set_value(str_replace("\r",'',$etempl->style));
$template->add_node($styles);
}
$this->xul_overlay->add_node($template);
}
/**
* create an XML representation of an eTemplate
*
* @param etemplate $etempl eTemplate object to export
* @return string the XML
*/
function export($etempl)
{
if ($this->debug)
{
echo "<p>etempl->data = "; _debug_array($etempl->data);
}
$doc = new xmldoc();
$doc->add_comment('$'.'Id$');
$this->xul_overlay = new xmlnode('overlay'); // global for all add_etempl calls
$embeded_too = True;
$this->add_etempl($etempl,$embeded_too);
$doc->add_root($this->xul_overlay);
$xml = $doc->export_xml();
if ($this->debug)
{
echo "<pre>\n" . htmlentities($xml) . "\n</pre>\n";
}
return $xml;
}
/**
* create an eTemplate from it's XML representation
*
* @param object &$etempl eTemplate object to set
* @param string $data the XML
* @return array/string array with names of imported templates or error-message
*/
function import(&$etempl,$data)
{
if ($this->debug)
{
echo "<pre>\n" . htmlentities($data) . "\n</pre><p>\n";
}
$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
$vals = $index = '';
$ok = xml_parse_into_struct($parser, $data, $vals, $index);
if (!$ok || !is_array($vals))
{
$err = 'Error Line '.xml_get_current_line_number($parser).', Column '.xml_get_current_column_number($parser).
': '.xml_error_string(xml_get_error_code($parser));
}
xml_parser_free($parser);
if ($err != '')
{
return $err;
}
$parents = array();
$parent = null;
foreach($vals as $n => $node)
{
if ($this->debug)
{
echo "<h1>$n</h1><pre>".print_r($node,true)."</pre>";
}
$type = $node['type'];
$tag = $node['tag'];
$attr = is_array($node['attributes']) ? $node['attributes'] : array();
if ($attr['id'])
{
$attr['name'] = $attr['id']; unset($attr['id']);
}
if (isset($attr['options']) && $attr['options'] != '')
{
$attr['size'] = $attr['options']; unset($attr['options']);
}
if ($tag != 'textbox' && !isset($attr['type']))
{
$attr['type'] = $this->xul2widget[$tag] ? $this->xul2widget[$tag] : $tag;
}
if ($this->debug)
{
echo "<p>$node[level]: $tag/$type: value='$node[value]' attr=\n"; _debug_array($attr);
}
switch ($tag)
{
case 'overlay':
break;
case 'template':
case 'grid':
if ($type != 'open' && is_array($tab_attr)) // templates/grids in a tabpanel
{
$tab_names[] = $attr['name'];
break;
}
if ($tag == 'template' && $type != 'complete' && $node['level'] > 2) // level 1 is the overlay
{
return "Can't import nested $tag's !!!";
}
switch ($type)
{
case 'close':
if (!count($parents)) // templ import complet => save it
{
unset($parent); $parents = array();
$etempl->fix_old_template_format(); // set the depricated compat vars
// save tmpl to the cache, as the file may contain more then one tmpl
$cname = ($etempl->template == '' ? 'default' : $etempl->template).'/'.$etempl->name.
($etempl->lang == '' ? '' : '.'.$etempl->lang);
boetemplate::store_in_cache($etempl);
if ($this->debug)
{
$etempl->echo_tmpl();
}
$imported[] = $etempl->name;
}
else
{
// poping the last used parent from the end of the parents array (array_pop does not work with references)
$parent = &$parents[count($parents)-1];
unset($parents[count($parents)-1]);
}
break;
case 'open':
if (($is_root = is_null($parent))) // starting a new templ
{
$etempl->init($attr);
$etempl->children = array(); // init adds one grid by default
$parent = &$etempl; // parent is the template-object itself!
}
if ($tag == 'grid')
{
$size = '';
foreach(array('overflow','padding','spacing','class','border','height','width') as $opt)
{
$size = $attr[$opt] . ($size != '' ? ",$size" : '');
}
$grid = array( // empty grid
'type' => 'grid',
'name' => $attr['name'],
'data' => array(),
'cols' => 0,
'rows' => 0,
'size' => $size,
);
soetemplate::add_child($parent,$grid);
$parents[count($parents)] = &$parent;
$parent = &$grid;
unset($grid);
}
break;
case 'complete': // reference to an other template
$attr['type'] = 'template'; // might be grid in old xet-files
soetemplate::add_child($parent,$attr);
unset($attr);
break;
}
break;
case 'columns':
case 'rows':
break;
case 'column':
if ($type != 'complete')
{
return 'place widgets in <row> and not in <column> !!!';
}
$parent['data'][0][$etempl->num2chrs($parent['cols']++)] = $attr['width'] .
($attr['disabled'] ? ','.$attr['disabled'] : '');
break;
case 'row':
if ($type != 'open')
{
break;
}
$nul = null; soetemplate::add_child($parent,$nul); // null = new row
$parent['data'][0]['c'.$parent['rows']] = $attr['class'] . ($attr['valign'] ? ','.$attr['valign'] : '');
$parent['data'][0]['h'.$parent['rows']] = $attr['height'] .
($attr['disabled']||$attr['part'] ? ','.$attr['disabled'] : '').
($attr['part'] ? ','.$attr['part'] : '');
break;
case 'styles':
$etempl->style = trim($node['value']);
break;
case 'tabbox':
if ($type == 'open')
{
$tab_labels = $tab_helps = $tab_names = array();
$tab_attr = $attr;
}
else
{
$tab_attr['type'] = 'tab';
$tab_attr['label'] = implode('|',$tab_labels);
$tab_attr['name'] = implode('|',$tab_names);
$tab_attr['help'] = implode('|',$tab_helps);
$tab_attr['span'] .= $tab_attr['class'] ? ','.$tab_attr['class'] : '';
unset($tab_attr['class']);
soetemplate::add_child($parent,$tab_attr);
unset($tab_attr);
}
break;
case 'tabs':
case 'tabpanels':
break;
case 'tab':
if ($type != 'close')
{
$tab_labels[] = $attr['label'];
$tab_helps[] = $attr['statustext'];
}
break;
case 'menupopup':
if (is_array($menulist_attr))
{
$attr['help'] = $attr['statustext']; unset($attr['statustext']);
unset($menulist_attr['type']);
$menulist_attr += $attr;
}
break;
case 'menulist':
if ($type == 'open')
{
$menulist_attr = $attr;
}
else
{
soetemplate::add_child($parent,$menulist_attr);
unset($menulist_attr);
}
break;
case 'split':
case 'vbox':
case 'hbox':
case 'deck':
case 'groupbox':
case 'box':
if ($type != 'close') // open or complete
{
$attr['size'] = '0'.($attr['orient'] || $attr['size'] ? ','.$attr['orient'].
($attr['size'] ? ','.$attr['size'] : '') : '');
$attr['span'] .= $attr['class'] ? ','.$attr['class'] : '';
unset($attr['class']);
soetemplate::add_child($parent,$attr);
$parents[count($parents)] = &$parent; // $parents[] does not always the same - strange
$parent = &$attr;
unset($attr);
}
if ($type != 'open') // close or complete
{
// poping the last used parent from the end of the parents array (array_pop does not work with references)
$parent = &$parents[count($parents)-1];
unset($parents[count($parents)-1]);
}
break;
case 'caption': // caption of (group)box
if ($parent['type'] == 'groupbox')
{
$parent['label'] = $attr['label'];
}
break;
// the following labels create automaticaly a child-entry in their parent
case 'textbox':
if ($attr['multiline'])
{
unset($attr['multiline']);
$attr['type'] = 'textarea';
$attr['size'] = $attr['rows'] . ($attr['cols'] ? ','.$attr['cols'] : '');
unset($attr['cols']);
unset($attr['rows']);
}
elseif ($attr['type']) // integer,float
{
$attr['size'] = $attr['min'] . ($attr['max'] ? ','.$attr['max'] : ($attr['size'] ? ',':'')) . ','.$attr['size'];
unset($attr['min']);
unset($attr['max']);
}
else // input
{
$attr['type'] = 'text';
$attr['size'] .= $attr['maxlength']!='' ? ','.$attr['maxlength'] : '';
unset($attr['maxlength']);
}
// fall-through
default:
switch ($tag)
{
case 'description':
case 'label':
$attr['label'] = $attr['value'];
unset($attr['value']);
break;
case 'template':
$attr['size'] = $attr['content'];
unset($attr['content']);
break;
case 'image':
$attr['name'] = $attr['src'];
unset($attr['src']);
$this->set_legacy_options($tag, $attr);
break;
case 'listbox':
$attr['size'] = preg_replace('/,*$/','',$attr['rows'].','.$attr['size']);
unset($attr['rows']);
break;
case 'button':
if ($attr['image'] || $attr['ro_image'])
{
$attr['size'] = $attr['image'] . ($attr['ro_image'] ? ','.$attr['ro_image'] : '');
unset($attr['image']); unset($attr['ro_image']);
}
break;
case 'nextmatch':
$this->set_legacy_options($tag, $attr);
break;
}
$attr['help'] = $attr['statustext']; unset($attr['statustext']);
$attr['span'] .= $attr['class'] ? ','.$attr['class'] : ''; unset($attr['class']);
if ($type == 'close')
{
break;
}
soetemplate::add_child($parent,$attr);
unset($attr);
break;
}
if ($this->debug)
{
echo "<b>parent</b><pre>".print_r($parent,true)."</pre>";
echo "<b>parents</b><pre>".print_r($parents,true)."</pre>";
echo "<b>children</b><pre>".print_r($etempl->children,true)."</pre>";
}
}
return $imported;
}
/**
* re-assemble legacy options in "size" attribute
*
* @param string $tag
* @param array &$attr
*/
function set_legacy_options($tag, &$attr)
{
// re-assemble legacy options in "size" attribute
if (empty($attr['size']) && $this->widget2xul[$tag]['size'])
{
foreach(explode(',', $this->widget2xul[$tag]['size']) as $l_attr)
{
$attr['size'] .= ($attr['size'] ? ',' : '').$attr[$l_attr];
unset($attr[$l_attr]);
}
while(substr($attr['size'], -1) == ',')
{
$attr['size'] = substr($attr['size'], 0, -1);
}
}
}
}

View File

@ -1,57 +0,0 @@
<?php
/**
* EGroupware - eTemplate sidebox
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/
$menu_title = $GLOBALS['egw_info']['apps'][$appname]['title'] . ' '. lang('Menu');
$file = Array(
'eTemplate Editor' => $GLOBALS['egw']->link('/index.php','menuaction=etemplate.editor.edit'),
'DB-Tools' => $GLOBALS['egw']->link('/index.php','menuaction=etemplate.db_tools.edit'),
'_NewLine_', // give a newline
'developer_tools' => $GLOBALS['egw']->link('/index.php','menuaction=etemplate.uilangfile.index'),
);
if($GLOBALS['egw_info']['flags']['currentapp'] == 'etemplate')
{
display_sidebox($appname,$menu_title,$file);
}
$menu_title = lang('Documentation');
$docs = $GLOBALS['egw_info']['server']['webserver_url'].'/etemplate/doc/';
$doc_file = Array(
array(
'text' => 'eTemplate2 Reference',
'link' => egw::link('/index.php','menuaction=api.EGroupware\\Api\\Etemplate\\WidgetBrowser.index', 'etemplate'),
),
array(
'text' => 'eTemplate Tutorial',
'link' => $docs.'etemplate.html',
'target' => 'docs'
),
array(
'text' => 'eTemplate Reference',
'link' => $docs.'reference.html',
'target' => 'docs'
),
array(
'text' => 'eGroupWare '.lang('Documentation'),
'no_lang' => True,
'link' => 'http://egroupware.org/wiki/DeveloperDocs',
'target' => 'docs'
),
array(
'text' => 'CSS properties',
'link' => 'http://www.w3.org/TR/REC-CSS2/propidx.html',
'target' => 'docs'
),
);
if($GLOBALS['egw_info']['flags']['currentapp'] == 'etemplate')
{
display_sidebox($appname, $menu_title, $doc_file);
}

View File

@ -1,14 +0,0 @@
<?php
/**
* eGroupWare - eTemplates - Editor
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @package etemplate
* @copyright (c) 2002-8 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
header('Location: ../index.php?menuaction=etemplate.editor.edit'.
(isset($_GET['sessionid']) ? '&sessionid='.$_GET['sessionid'].'&kp3='.$_GET['kp3'] : ''));

View File

@ -1,443 +0,0 @@
/**
* Javascript file for AJAX select widget
*
* @author Nathan Gray <nathangray@sourceforge.net>
*
* @param widget_id the id of the ajax_select_widget
* @param onchange function to call if the value of the select widget is changed
* @param options the query object containing callback and settings
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage extensions
* @link http://www.egroupware.org
*
* @version $Id$
*/
//xajaxDebug = 1;
var current_app = 'etemplate';
/**
* Settings for the timeout to prevent flooding the server with requests
*
* Adjust ajax_select_timeout to change how long to wait before sending the request (in ms)
*/
var ajax_select_timer_id = 0;
var ajax_select_timeout = 300;
var ajax_select_event = null;
// These keys will not trigger a search if the results box is currently displayed
var no_search_keys = [
'9', // Tab
'38', '63232', // Up
'40', '63233' // Down
];
function ajax_select_widget_setup(widget_id, onchange, options, currentapp) {
current_app = currentapp;
if(onchange) {
if(onchange == 1) {
onchange = function() {submitit(this.form, this.value);};
} else {
eval("onchange = function(e) { " + onchange + ";}");
}
var value = document.getElementById(widget_id + '[value]');
if(value) {
if(value.addEventListener) {
value.addEventListener('change', onchange, true);
} else {
var old = (value.onchange) ? value.onchange : function() {};
value.onchange = function(e) {
old(e);
onchange(e);
};
}
}
}
var widget = document.getElementById(widget_id + '[search]');
if(widget) {
widget.setAttribute('autocomplete', 'off');
if(widget.addEventListener) {
widget.addEventListener('keydown', checkKey, true);
widget.addEventListener('keyup', timer_change, false);
widget.addEventListener('blur', hideBox, false);
} else {
widget.onkeyup = timer_change;
widget.onblur = hideBox;
widget.onkeydown = checkKey;
}
// Set results
var results = document.createElement('div');
results.id = widget_id + '[results]';
results.className = 'resultBox';
results.style.position = 'absolute';
// check if IE, if it is, fix the position
if (document.all) {
results.style.marginLeft = 0 - widget.offsetWidth - 2 * widget.offsetLeft - 1;
results.style.marginTop = widget.offsetHeight + 1;
}
results.style.zIndex = 50;
results.options = options;
results.innerHTML = "";
widget.parentNode.appendChild(results);
}
var value = document.getElementById(widget_id + '[value]');
if(value) {
value.style.display = 'none';
}
}
function checkKey(e, value) {
if(!e) {
var e = window.event;
}
/*
* We check for Tab, Up and Down
*/
var interested = false;
for(var i = 0; i < no_search_keys.length; i++) {
if(e.keyCode == no_search_keys[i]) {
interested = true;
break;
}
}
if (!interested) {
return; // The user has not pressed anything we're interested in
}
if(e.target) {
var target = e.target;
} else if (e.srcElement) {
var target = e.srcElement;
}
if(target) {
if (target.nodeType == 3) { // defeat Safari bug
target = target.parentNode;
}
}
var id = target.id;
var base_id = id.substr(0, id.lastIndexOf('['));
var results = document.getElementById(base_id + '[results]');
// Consume event so search doesn't go
if(results.childNodes.length > 0) {
e.cancelBubble = true;
if(e.stopPropegation) e.stopPropegation();
clearTimeout(ajax_select_timer_id);
} else {
return false;
}
// Up and down arrows
switch (e.keyCode) {
// Up
case 38:
case 63232:
if(results.current) {
results.current.className = results.current.className.replace(' resultBoxSelected','');
}
if(results.current && results.current.previousSibling && results.current.previousSibling.childNodes.length > 2) {
results.current = results.current.previousSibling;
} else {
var elements = results.childNodes;
results.current = elements[elements.length - 1];
}
results.current.className += ' resultBoxSelected';
break;
// Down
case 40:
case 63233:
if(results.current) {
results.current.className = results.current.className.replace(' resultBoxSelected','');
}
if(results.current && results.current.nextSibling && results.current.nextSibling.childNodes.length > 2) {
results.current = results.current.nextSibling;
} else {
var elements = results.childNodes;
for (var i = 0; i < elements.length; i++) {
elem = elements.item(i);
if (elem.value) {
results.current = elem;
break; // We have found the first selection
}
}
}
results.current.className += ' resultBoxSelected';
break;
// Tab: Select current element
case 9:
var elem;
if(results.current && results.current.value) {
elem = results.current;
} else {
var elements = document.getElementById(base_id + '[results]').childNodes;
for (var i = 0; i < elements.length; i++) {
elem = elements.item(i);
if (elem.value) {
break; // We have found the first selection
}
}
}
if (!elem) return;
var event;
if(document.createEvent && document.dispatchEvent) {
// Most
event = document.createEvent('MouseEvents');
event.initEvent('click', true, true);
elem.dispatchEvent(event);
} else {
// IE
event = document.createEventObject();
elem.fireEvent('onclick', event);
}
break;
}
}
/**
* Set a timeout to prevent user from flooding the server with requests as
* they type. Waits to see if the user is still typing before sending the
* request. Adjust ajax_select_timeout to change how long to wait (in ms).
*/
function timer_change(e, value) {
if ( ajax_select_timer_id != 0) {
clearTimeout(ajax_select_timer_id);
}
if(!e) {
var e = cloneObject(window.event);
} else {
var e = cloneObject(e);
}
ajax_select_event = e;
ajax_select_timer_id = setTimeout(
function() {
change(e, value);
},
ajax_select_timeout
);
}
function change(e, value) {
if(!e) {
var e = window.event;
}
if(e.target) {
var target = e.target;
} else if (ajax_select_event) {
var e = ajax_select_event;
ajax_select_event = null;
if(e.target) {
var target = e.target;
} else if (e.srcElement) {
var target = e.srcElement;
}
} else if (e.srcElement) {
var target = e.srcElement;
}
if(target) {
if (target.nodeType == 3) { // defeat Safari bug
target = target.parentNode;
}
var id = target.id;
var value = target.value;
} else if (typeof(e) == 'string' ) {
var id = e;
if(value) {
var value = value;
} else {
var value = e.value;
}
var set_id = id.substr(0, id.lastIndexOf('['));
} else {
alert('Error in events');
return;
}
var base_id = id.substr(0, id.lastIndexOf('['));
if(document.getElementById(base_id + '[results]')) {
set_id = base_id + '[results]';
/*
* We check for Tab, Up and Down
*/
var interested = false;
var keycode = '';
for(var i = 0; i < no_search_keys.length; i++) {
if(e.which) {
keycode = e.which;
} else if(e && e.keyCode) {
keycode = e.keyCode;
}
if(keycode == no_search_keys[i]) {
interested = true;
break;
}
}
if (interested && document.getElementById(set_id).style.display == 'block') {
clearTimeout(ajax_select_timer_id);
return; // Results are shown, allow keys to move the selection cursor
}
} else {
set_id = base_id + '[search]';
}
var query = document.getElementById(set_id).options;
if(document.getElementById(base_id + '[filter]')) {
query.filter = document.getElementById(base_id + '[filter]').value;
}
// Hide selectboxes for IE
if(document.all) {
var selects = document.getElementsByTagName('select');
for(var i = 0; i < selects.length; i++) {
selects[i].style.visibility = 'hidden';
}
}
xajax_doXMLHTTP(current_app + ".ajax_select_widget.ajax_search.etemplate", id, value, set_id, query, document.getElementById('etemplate_exec_id').value);
}
/**
* Deep copy an object
* Used because IE thinks its a good idea to use a global var for events
*/
function cloneObject(obj) {
var clone = {};
for(var i in obj) {
clone[i] = obj[i];
}
return clone;
}
/* Remove options from a results box
* @param id - The id of the select
*/
function remove_ajax_results(id) {
if(document.getElementById(id)) {
var element = document.getElementById(id);
if (element.tagName == 'DIV') {
element.innerHTML = '';
}
}
}
/* Add an option to a result box
* @param id - The id of the result box
* @param key - The key of the option
* @param value - The value of the option
* @param row - The html for the row to display
*/
function add_ajax_result(id, key, value, row) {
var resultbox = document.getElementById(id);
if(resultbox) {
if (resultbox.tagName == 'DIV') {
var base_id = resultbox.id.substr(0, resultbox.id.lastIndexOf('['));
var search_id = base_id + '[search]';
var value_id = base_id + '[value]';
resultbox.style.display = 'block';
var result = document.createElement('div');
result.className = (resultbox.childNodes.length % 2) ? 'row_on' : 'row_off';
if(key) {
result.value = new Object();
result.value.key = key;
result.value.value = value;
result.value.search_id = search_id;
result.value.value_id = value_id;
result.innerHTML = row;
// when they click, add that item to the value hidden textbox
if(result.addEventListener) {
result.addEventListener('click', select_result, true);
} else {
result.onclick = select_result;
}
} else {
result.innerHTML += row + "<br />";
}
resultbox.appendChild(result);
}
}
}
function select_result(e) {
// when they click, add that item to the value textbox & call onchange()
if(!e) {
var e = window.event;
}
if(e.target) {
var target = e.target;
} else if (e.srcElement) {
var target = e.srcElement;
}
while(!target.value && target != document) {
target = target.parentNode;
}
var value = document.getElementById(target.value.value_id);
var search = document.getElementById(target.value.search_id);
if(value) {
value.value = target.value.key;
}
if(search) {
var string = target.value.value;
string = string.replace(/&amp;/g, '&');
string = string.replace(/&lt;/g, '<');
string = string.replace(/&gt;/g, '>');
search.value = string;
var event;
if(document.createEvent) {
// Most
event = document.createEvent('HTMLEvents');
event.initEvent('change', true, true);
return value.dispatchEvent(event);
} else {
// IE
event = document.createEventObject();
return value.fireEvent('onchange', event);
}
}
}
function hideBox(e) {
if(!e) {
var e = window.event;
}
if(e.target) {
var target = e.target;
} else if (e.srcElement) {
var target = e.srcElement;
}
if(target) {
if (target.nodeType == 3) { // defeat Safari bug
target = target.parentNode;
}
}
var set_id = target.id.substr(0, target.id.lastIndexOf('[')) + '[results]';
setTimeout("document.getElementById('" + set_id + "').style.display = 'none'", 200);
var selects = document.getElementsByTagName('select');
// Un-hide select boxes for IE
if(document.all) {
for(var i = 0; i < selects.length; i++) {
selects[i].style.visibility = 'visible';
}
}
}

View File

@ -1,427 +0,0 @@
/**
* eGroupWare eTemplate Extension - AJAX Select Widget
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage api
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/
/**
* Handle HTML5 validation on tabs
*/
egw_LAB.wait(function() {
jQuery().ready(function() {
jQuery('.tab_body :input').bind('invalid', function(e) {
// Activate the appropriate tab
var tab = jQuery(this).parentsUntil('.tab_body').last();
var alltabs = [tab.attr("id")];
tab.siblings('div').each(function() {
alltabs.push(this.id);
});
activate_tab(tab.attr("id"), alltabs.join('|'));
});
// focus on input with tabindex=1
jQuery('input[tabindex="1"],select[tabindex="1"],textarea[tabindex="1"]').focus();
});
});
function submitit(form,name)
{
//alert(name+' pressed');
form.submit_button.value = name;
form.submit();
form.submit_button.value = '';
return false;
}
function set_element(form,name,value)
{
//alert('set_element: '+name+'='+value);
for (i = 0; i < form.length; i++)
{
if (form.elements[i].name == name)
{
//alert('set_element: '+name+'='+value);
form.elements[i].value = value;
//alert(name+'='+form.elements[i].value);
}
}
}
function set_element2(form,name,vname)
{
//alert('set_element2: '+name+'='+vname);
for (i = 0; i < form.length; i++)
{
if (form.elements[i].name == vname)
{
value = form.elements[i].value;
}
}
//alert('set_element2: '+name+'='+value);
for (i = 0; i < form.length; i++)
{
if (form.elements[i].name == name)
{
form.elements[i].value = value;
}
}
}
function activate_tab(tab,all_tabs,name)
{
var tabs = all_tabs.split('|');
var parts = tab.split('.');
var last_part = parts.length-1;
for (n = 0; n < tabs.length; n++)
{
var t = tabs[n];
if (t.indexOf('.') < 0 && parts.length > 1)
{
parts[last_part] = t;
t = parts.join('.');
}
document.getElementById(t).style.display = t == tab ? 'inline' : 'none';
document.getElementById(t+'-tab').className = 'etemplate_tab'+(t == tab ? '_active th' : ' row_on');
}
// activate FCK in newly activated tab for Gecko browsers
if (!document.all)
{
try {
var t = document.getElementById(tab);
var inputs = t.getElementsByTagName('input');
for (i = 0; i < inputs.length;i++) {
editor = FCKeditorAPI.GetInstance(inputs[i].name);
if (editor && editor.EditorDocument && editor.EditMode == FCK_EDITMODE_WYSIWYG) {
editor.SwitchEditMode();
editor.SwitchEditMode();
break;
}
}
}
catch(e) { } // ignore the error if FCKeditorAPI is not loaded
}
if (name) {
set_element(document.eTemplate,name,tab);
}
}
/* proxy to to add options to a selectbox, needed by IE, but works everywhere */
function selectbox_add_option(id,label,value,do_onchange)
{
selectBox = document.getElementById(id);
/*alert('selectbox_add_option('+id+','+label+','+value+') '+selectBox);*/
var search_val = value.split(':');
for (i=0; i < selectBox.length; i++) {
var selectvalue = selectBox.options[i].value.split(':');
if (selectvalue[0] == search_val[0]) {
selectBox.options[i] = null;
selectBox.options[selectBox.length] = new Option(label,value,false,true);
break;
}
}
if (i >= selectBox.length) {
selectBox.options[selectBox.length] = new Option(label,value,false,true);
}
if (selectBox.onchange && do_onchange) selectBox.onchange();
// If chosen is loaded, trigger update
if(selectBox && $j().chosen) {
$j(selectBox).trigger("liszt:updated");
}
}
/* toggles all checkboxes named name in form form, to be used as custom javascript in onclick of a button/image */
function toggle_all(form,name)
{
var all_set = true;
/* this is for use with a sub-grid. To use it pass "true" as third parameter */
if(toggle_all.arguments.length > 2 && toggle_all.arguments[2] == true)
{
el = form.getElementsByTagName("input");
for (var i = 0; i < el.length; i++)
{
if(el[i].name.substr(el[i].name.length-12,el[i].name.length) == '[checkbox][]' && el[i].checked)
{
all_set = false;
break;
}
}
for (var i = 0; i < el.length; i++)
{
if(el[i].name.substr(el[i].name.length-12,el[i].name.length) == '[checkbox][]')
{
el[i].checked = all_set;
}
}
}
else
{
var checkboxes = document.getElementsByName(name);
for (var i = 0; i < checkboxes.length; i++)
{
if (!checkboxes[i].checked)
{
all_set = false;
break;
}
}
for (var i = 0; i < checkboxes.length; i++)
{
checkboxes[i].checked = !all_set;
}
}
}
/* gets the values of the named widgets (use the etemplate-name, not the form-name) and creates an url from it */
function values2url(form,names)
{
url = '';
names = names.split(',');
for(i=0; i < names.length; i++)
{
form_name = names[i];
b = form_name.indexOf('[');
if (b < 0) {
form_name = 'exec['+form_name+']';
} else {
form_name = 'exec['+form_name.slice(0,b-1)+']'+form_name.slice(b,99);
}
//alert('Searching for '+form_name);
for (f=0; f < form.elements.length; f++) {
element = form.elements[f];
//alert('checking '+element.name);
if (element.name.slice(0,form_name.length) == form_name) {
//alert('found '+element.name+', value='+element.value);
if (element.type == 'checkbox' || element.type == 'radio') { // checkbox or radio
if (element.checked) url += '&'+element.name+'='+element.value;
} else if (element.options) { // selectbox
for(opt=0; opt < element.options.length; opt++) {
//alert('found '+element.name+' option['+opt+'] = '+element.options[opt].value+ ' = '.element.options[opt].text+': '+element.options[opt].selected);
if (element.options[opt].selected) url += '&'+element.name+(element.name.indexOf('[]') >= 0 || !element.multiple ? '=' : '[]=')+element.options[opt].value;
}
} else if (element.value != null) {
url += '&'+element.name+'='+element.value;
}
}
}
}
//alert('url='+url);
return url+'&etemplate_exec_id='+form['etemplate_exec_id'].value;
}
// submits the whole form via ajax to a given menuaction or the current one if '' passed
function ajax_submit(form,menuaction)
{
if(!menuaction) menuaction = form.action.replace(/.+menuaction=/,'');
xajax_doXMLHTTP(menuaction+'./etemplate/process_exec', xajax.getFormValues(form));
}
// sets value (v) of style property (p) for all given elements of type (t) and class (c)
// eg. set_style_by_class('td','hide','visibility','visible')
function set_style_by_class(t,c,p,v)
{
//alert('set_style_by_class('+t+','+c+','+p+','+v+')');
var elements;
if(t == '*') {
// '*' not supported by IE/Win 5.5 and below
elements = (document.all) ? document.all : document.getElementsByTagName('*');
} else {
elements = document.getElementsByTagName(t);
}
for(var i = 0; i < elements.length; i++){
var node = elements.item(i);
for(var j = 0; j < node.attributes.length; j++) {
if(node.attributes.item(j).nodeName.toLowerCase() == 'class') {
if(node.attributes.item(j).nodeValue.indexOf(' ') == 0) {
// Single class
if(node.attributes.item(j).nodeValue == c) {
eval('node.style.' + p + " = '" +v + "'");
}
} else {
// Multiple classes
var classes = node.attributes.item(j).nodeValue.split(' ');
for(var k = 0; k < classes.length; k++) {
if(classes[k] == c) {
eval('node.style.' + p + " = '" +v + "'");
}
}
}
}
}
}
}
function xajax_eT_wrapper(obj) {
if (typeof(obj) == 'object') {
set_style_by_class('div','popupManual noPrint','display','none');
set_style_by_class('div','ajax-loader','display','inline');
obj.form.submit_button.value = obj.name;
var menuaction = obj.form.action.replace(/.+menuaction=/,'');
xajax_doXMLHTTP(menuaction+'./etemplate/process_exec', xajax.getFormValues(obj.form));
}
else {
set_style_by_class('div','ajax-loader','display','none');
set_style_by_class('div','popupManual noPrint','display','inline');
}
}
function disable_button(id) {
document.getElementById(id).disabled = 'true';
document.getElementById(id).style.color = 'gray';
}
function enable_button(id) {
document.getElementById(id).disabled = 'false';
document.getElementById(id).style.color = '';
}
// returns selected checkboxes from given 'var form' which REAL names end with 'var suffix'
function get_selected(form,suffix) {
selected = '';
el = form.getElementsByTagName('input');
for (var i = 0; i < el.length; i++) {
if(el[i].name.substr(el[i].name.length-suffix.length,el[i].name.length) == suffix && el[i].checked) {
if(selected.length > 0) {
selected += ',';
}
selected += el[i].value;
}
}
return selected;
}
// returns selected checkboxes from given 'var form' which REAL names end with 'var suffix'
function get_selected_array(form,suffix) {
selected = new Array();
el = form.getElementsByTagName('input');
for (var i = n = 0; i < el.length; i++) {
if(el[i].name.substr(el[i].name.length-suffix.length,el[i].name.length) == suffix && el[i].checked) {
selected[n++] = el[i].value;
}
}
return selected;
}
// set certain comma-separated values in a multiselection (div with checkboxes, used as replacement for a multiselection)
function set_multiselection(name,values,reset)
{
//alert("set_multiselection('"+name+"','"+values+"',"+reset+")");
checkboxes = document.getElementsByName(name);
div = document.getElementById(name.substr(0,name.length-2));
div_first = div.firstChild;
values = ','+values+',';
for (var i = 0; i < checkboxes.length; i++) {
checkbox = checkboxes[i];
value = values.indexOf(','+checkbox.value+',') >= 0;
if (reset || value) {
//alert(checkbox.name+': value='+checkbox.value+', checked='+checkbox.checked+' --> '+value);
if (value && checkbox.parentNode != div_first) {
br = checkbox.parentNode.nextSibling;
div.insertBefore(div.removeChild(checkbox.parentNode),div_first);
div.insertBefore(div.removeChild(br),div_first);
}
checkbox.checked = value;
}
}
}
// add an other upload
function add_upload(upload)
{
var parent = upload.parentNode;
var newUpload = upload.cloneNode(true);
parent.insertBefore(newUpload,upload);
var br = document.createElement('br');
parent.insertBefore(br,upload);
newUpload.value = '';
newUpload.id += parent.childNodes.length;
parent.insertBefore(upload,newUpload);
}
// resizes popups to fit their content in
function popup_resize()
{
var widest = 0, highest = 0, smallest = window.innerWidth, width2grow, height2grow;
// find all elements and check their size
var divs = document.getElementsByTagName("div");
for(var i = 0;i < divs.length;i++)
{
if(divs[i].offsetWidth + divs[i].offsetLeft > widest)
widest = divs[i].offsetWidth + divs[i].offsetLeft;
if(divs[i].offsetHeight + divs[i].offsetTop > highest)
highest = divs[i].offsetHeight + divs[i].offsetTop;
if(divs[i].offsetLeft > 0 && divs[i].offsetLeft < smallest)
smallest = divs[i].offsetLeft;
}
var tables = document.getElementsByTagName("table");
for(var i = 0;i < tables.length;i++)
{
if(tables[i].offsetWidth + tables[i].offsetLeft > widest)
widest = tables[0].offsetWidth + tables[i].offsetLeft;
if(tables[i].offsetHeight + tables[i].offsetTop > highest)
highest = tables[0].offsetHeight + tables[i].offsetTop;
if(tables[i].offsetLeft > 0 && tables[i].offsetLeft < smallest)
smallest = tables[i].offsetLeft;
}
var labels = document.getElementsByTagName("label");
for(var i = 0;i < labels.length;i++)
{
if(labels[i].offsetWidth + labels[i].offsetLeft > widest)
widest = labels[i].offsetWidth + labels[i].offsetLeft;
if(labels[i].offsetHeight + labels[i].offsetTop > highest)
highest = labels[i].offsetHeight + labels[i].offsetTop;
if(labels[i].offsetLeft > 0 && labels[i].offsetLeft < smallest)
smallest = labels[i].offsetLeft;
}
var inputs = document.getElementsByTagName("input");
for(var i = 0;i < inputs.length;i++)
{
if(inputs[i].offsetWidth + inputs[i].offsetLeft > widest)
widest = inputs[i].offsetWidth + inputs[i].offsetLeft;
if(inputs[i].offsetHeight + inputs[i].offsetTop > highest)
highest = inputs[i].offsetHeight + inputs[i].offsetTop;
if(inputs[i].offsetLeft > 0 && inputs[i].offsetLeft < smallest)
smallest = inputs[i].offsetLeft;
}
// calculate the width and height the window has to grow
width2grow = widest - window.innerWidth + (smallest != window.innerWidth ? Math.max(smallest, 10) : 10);
height2grow = highest - window.innerHeight + 10;
if(width2grow > 0 && window.outerWidth + width2grow < screen.availWidth * 0.8)
{
window.moveBy(-(width2grow / 2), 0);
window.resizeBy(width2grow, 0);
}
if(height2grow > 0)
{
if(window.outerHeight + height2grow > screen.availHeight)
{
window.resizeTo(window.outerWidth, screen.availHeight);
}
else
{
var positionY = (document.all?window.screenTop:window.screenY);
var moveMe = height2grow / 2;
if ( moveMe <= positionY )
{
moveMe = -(moveMe);
}
else
{
moveMe = 0;
if (positionY > 0) moveMe = -(positionY);
}
//moveMe = -(height2grow / 2);
//alert('hallo:'+positionY+' moveMe:'+moveMe);
window.moveBy(0, moveMe);
window.resizeBy(0, height2grow);
}
}
}

View File

@ -1,369 +0,0 @@
/**
* EGroupware eTemplate nextmatch row action object interface
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage api
* @link http://www.egroupware.org
* @author Andreas Stöckel (as AT stylite.de)
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/
/**
* Contains the action object interface implementation for the nextmatch widget
* row.
*/
var EGW_SELECTMODE_DEFAULT = 0;
var EGW_SELECTMODE_TOGGLE = 1;
/**
* An action object interface for each nextmatch widget row - "inherits" from
* egwActionObjectInterface
*/
function nextmatchRowAOI(_node, _selectMode)
{
var aoi = new egwActionObjectInterface();
aoi.node = _node;
aoi.selectMode = _selectMode;
aoi.checkBox = ($j(":checkbox", aoi.node))[0];
// Rows without a checkbox OR an id set are unselectable
if (typeof aoi.checkBox != "undefined" || _node.id)
{
aoi.doGetDOMNode = function() {
return aoi.node;
}
// Prevent the browser from selecting the content of the element, when
// a special key is pressed.
$j(_node).mousedown(egwPreventSelect);
// Now append some action code to the node
selectHandler = function(e) {
// Reset the focus so that keyboard navigation will work properly
// after the element has been clicked
egwUnfocus();
// Reset the prevent selection code (in order to allow wanted
// selection of text)
_node.onselectstart = null;
if (e.target != aoi.checkBox)
{
var selected = egwBitIsSet(aoi.getState(), EGW_AO_STATE_SELECTED);
var state = egwGetShiftState(e);
switch (aoi.selectMode)
{
case EGW_SELECTMODE_DEFAULT:
aoi.updateState(EGW_AO_STATE_SELECTED,
!egwBitIsSet(state, EGW_AO_SHIFT_STATE_MULTI) || !selected,
state);
break;
case EGW_SELECTMODE_TOGGLE:
aoi.updateState(EGW_AO_STATE_SELECTED, !selected,
egwSetBit(state, EGW_AO_SHIFT_STATE_MULTI, true));
break;
}
}
};
if (egwIsMobile()) {
_node.ontouchend = selectHandler;
} else {
$j(_node).click(selectHandler);
}
$j(aoi.checkBox).change(function() {
aoi.updateState(EGW_AO_STATE_SELECTED, this.checked, EGW_AO_SHIFT_STATE_MULTI);
});
// Don't execute the default action when double clicking on an entry
$j(aoi.checkBox).dblclick(function() {
return false;
});
aoi.doSetState = function(_state) {
var selected = egwBitIsSet(_state, EGW_AO_STATE_SELECTED);
if (this.checkBox)
{
this.checkBox.checked = selected;
}
$j(this.node).toggleClass('focused',
egwBitIsSet(_state, EGW_AO_STATE_FOCUSED));
$j(this.node).toggleClass('selected',
selected);
}
}
return aoi;
}
/**
* Default action for nextmatch rows, runs action specified _action.data.nm_action: see nextmatch_widget::egw_actions()
*
* @param _action action object with attributes caption, id, nm_action, ...
* @param _senders array of rows selected
*/
function nm_action(_action, _senders)
{
// ignore checkboxes, unless they have an explicit defined nm_action
if (_action.checkbox && (!_action.data || typeof _action.data.nm_action == 'undefined')) return;
if (typeof _action.data == 'undefined' || !_action.data) _action.data = {};
if (typeof _action.data.nm_action == 'undefined') _action.data.nm_action = 'submit';
var ids = "";
for (var i = 0; i < _senders.length; i++)
{
ids += (_senders[i].id.indexOf(',') >= 0 ? '"'+_senders[i].id.replace(/"/g,'""')+'"' : _senders[i].id) +
((i < _senders.length - 1) ? "," : "");
}
//console.log(_action); console.log(_senders);
var mgr = _action.getManager();
var select_all = mgr.getActionById("select_all");
var confirm_msg = (_senders.length > 1 || select_all && select_all.checked) &&
typeof _action.data.confirm_multiple != 'undefined' ?
_action.data.confirm_multiple : _action.data.confirm;
// let user confirm the action first (if not select_all set and nm_action == 'submit' --> confirmed later)
if (!(select_all && select_all.checked && _action.data.nm_action == 'submit') &&
typeof _action.data.confirm != 'undefined')
{
if (!confirm(confirm_msg)) return;
}
// in case we only need to confirm multiple selected (only _action.data.confirm_multiple)
else if (typeof _action.data.confirm_multiple != 'undefined' && (_senders.length > 1 || select_all && select_all.checked))
{
if (!confirm(_action.data.confirm_multiple)) return;
}
var url = '#';
if (typeof _action.data.url != 'undefined')
{
url = _action.data.url.replace(/(\$|%24)id/,encodeURIComponent(ids));
}
var target = null;
if (typeof _action.data.target != 'undefined')
{
target = _action.data.target;
}
switch(_action.data.nm_action)
{
case 'alert':
alert(_action.caption + " (\'" + _action.id + "\') executed on rows: " + ids);
break;
case 'location':
if (typeof _action.data.targetapp != 'undefined')
{
top.egw_appWindowOpen(_action.data.targetapp, url);
}
else if(target)
{
window.open(url, target);
}
else
{
window.location.href = url;
}
break;
case 'popup':
egw_openWindowCentered2(url,target,_action.data.width,_action.data.height);
break;
case 'egw_open':
var params = _action.data.egw_open.split('-'); // type-appname-idNum (idNum is part of id split by :), eg. "edit-infolog"
console.log(params);
var egw_open_id = _senders[0].id;
if (typeof params[2] != 'undefined') egw_open_id = egw_open_id.split(':')[params[2]];
egw(params[1],window).open(egw_open_id,params[1],params[0],params[3],target);
break;
case 'open_popup':
// open div styled as popup contained in current form and named action.id+'_popup'
if (nm_popup_action == null)
{
nm_open_popup(_action, _senders);
break;
}
// fall through, if popup is open --> submit form
case 'submit':
// let user confirm select-all
if (select_all && select_all.checked)
{
// Use jQuery to decode all entities
if (!confirm((confirm_msg ? confirm_msg : jQuery('<span/>').html(_action.caption).text())+"\n\n"+select_all.hint)) return;
}
var checkboxes = mgr.getActionsByAttr("checkbox", true);
var checkboxes_elem = document.getElementById(mgr.etemplate_var_prefix+'[nm][checkboxes]');
if (checkboxes && checkboxes_elem)
for (var i in checkboxes)
checkboxes_elem.value += checkboxes[i].id + ":" + (checkboxes[i].checked ? "1" : "0") + ";";
document.getElementById(mgr.etemplate_var_prefix+'[nm][nm_action]').value = _action.id;
document.getElementById(mgr.etemplate_var_prefix+'[nm][selected]').value = ids;
if (typeof _action.data.button != 'undefined')
{
submitit(mgr.etemplate_form.context, mgr.etemplate_var_prefix+'[nm][rows]['+_action.data.button+']['+ids+']');
}
else
{
mgr.etemplate_form.submit();
}
// Clear action in case there's another one
document.getElementById(mgr.etemplate_var_prefix+'[nm][nm_action]').value = null;
break;
}
}
/**
* Callback to check if none of _senders rows has disableClass set
*
* @param _action egwAction object, we use _action.data.disableClass to check
* @param _senders array of egwActionObject objects
* @param _target egwActionObject object, get's called for every object in _senders
* @returns boolean true if none has disableClass, false otherwise
*/
function nm_not_disableClass(_action, _senders, _target)
{
return !$j(_target.iface.getDOMNode()).hasClass(_action.data.disableClass);
}
/**
* Callback to check if all of _senders rows have enableClass set
*
* @param _action egwAction object, we use _action.data.enableClass to check
* @param _senders array of egwActionObject objects
* @param _target egwActionObject object, get's called for every object in _senders
* @returns boolean true if none has disableClass, false otherwise
*/
function nm_enableClass(_action, _senders, _target)
{
return $j(_target.iface.getDOMNode()).hasClass(_action.data.enableClass);
}
/**
* Enable an _action, if it matches a given regular expresstion in _action.data.enableId
*
* @param _action egwAction object, we use _action.data.enableId to check
* @param _senders array of egwActionObject objects
* @param _target egwActionObject object, get's called for every object in _senders
* @returns boolean true if _target.id matches _action.data.enableId
*/
function nm_enableId(_action, _senders, _target)
{
if (typeof _action.data.enableId == 'string')
_action.data.enableId = new RegExp(_action.data.enableId);
return _target.id.match(_action.data.enableId);
}
/**
* Callback to check if a certain field (_action.data.fieldId) is (not) equal to given value (_action.data.fieldValue)
*
* If field is not found, we return false too!
*
* @param _action egwAction object, we use _action.data.fieldId to check agains _action.data.fieldValue
* @param _senders array of egwActionObject objects
* @param _target egwActionObject object, get's called for every object in _senders
* @returns boolean true if field found and has specified value, false otherwise
*/
function nm_compare_field(_action, _senders, _target)
{
var field = document.getElementById(_action.data.fieldId);
if (!field) return false;
var value = $j(field).val();
if (_action.data.fieldValue.substr(0,1) == '!')
return value != _action.data.fieldValue.substr(1);
return value == _action.data.fieldValue;
}
var nm_popup_action, nm_popup_senders = null;
/**
* Open popup for a certain action requiring further input
*
* Popup needs to have eTemplate name of action id plus "_popup"
*
* @param _action
* @param _senders
*/
function nm_open_popup(_action, _senders)
{
var popup = document.getElementById(_action.getManager().etemplate_var_prefix + '[' + _action.id + '_popup]');
if (popup) {
nm_popup_action = _action;
nm_popup_senders = _senders;
popup.style.display = 'block';
}
}
/**
* Submit a popup action
*/
function nm_submit_popup(button)
{
button.form.submit_button.value = button.name; // set name of button (sub-action)
// call regular nm_action to transmit action and senders correct
nm_action(nm_popup_action, nm_popup_senders);
}
/**
* Hide popup
*/
function nm_hide_popup(element, div_id)
{
var prefix = element.id.substring(0,element.id.indexOf('['));
var popup = document.getElementById(prefix+'['+div_id+']');
// Hide popup
if(popup) {
popup.style.display = 'none';
}
nm_popup_action = null;
nm_popup_senders = null;
return false;
}
/**
* Activate/click first link in row
*/
function nm_activate_link(_action, _senders)
{
// $j(_senders[0].iface.getDOMNode()).find('a:first').trigger('click'); not sure why this is NOT working
var a_href = $j(_senders[0].iface.getDOMNode()).find('a:first');
if (typeof a_href != undefined)
{
var target = a_href.attr('target');
var href = a_href.attr('href');
if (a_href.attr('onclick'))
a_href.click();
else if (target)
window.open(href,target);
else
window.location = href;
}
}

View File

@ -1,3 +0,0 @@
download developer_tools bg Изтегляне
remove developer_tools bg премахване
translation developer_tools bg Превод

View File

@ -1,74 +0,0 @@
add developer_tools ca afegir
add change developer_tools ca Afegir canvi
add more developer_tools ca Afegir més
add new phrase developer_tools ca Afegir nova frase
add phrase developer_tools ca Afegir frase
allows you to add a single phrase developer_tools ca Us permet afegir una frase
application developer_tools ca Aplicació
back developer_tools ca Tornar
cancel developer_tools ca Cancel·lar
change developer_tools ca Canviar
changelog entry has been added developer_tools ca Entrada afegida al registre de canvis
changelogs developer_tools ca Registres de canvis
clears the internal buffer, all changes made sofar are lost developer_tools ca Neteja l'emmagatzemament intern, tots els canvis fets fins ara es perdran
create new language file developer_tools ca Crear Nou Arxiu d'Idioma
create sgml file developer_tools ca Crear arxiu SGML
developer tools - preferences developer_tools ca Eines de traducció - preferències
developer_tools common ca Eines de Traducció
diary developer_tools ca Diari
done developer_tools ca Fet
download developer_tools ca Descarregar
download the lang-file to be saved in the apps setup-dir developer_tools ca Descarrega l'arxiu d'idioma per guardar-lo al directori "setup" de l'aplicació
edit developer_tools ca Editar
installed applications developer_tools ca Aplicacions instal·lades
language file management developer_tools ca Gestió d'arxius d'idioma
list changelogs developer_tools ca Llistar registres de canvi
load developer_tools ca Carregar
loading source langfile developer_tools ca Carregant arxiu d'idioma origen
loading target langfile developer_tools ca Carregant arxiu d'idioma destí
loads the selected lang-files, to be modified in the next steps developer_tools ca Carrega els arxius d'idioma seleccionats, per modificar-los a les passes següents
message developer_tools ca Missatge
message_id in english developer_tools ca Id. de missatge en Anglès
no file developer_tools ca Sense arxiu
ok developer_tools ca D'acord
original developer_tools ca Original
phrase in english (or empty if identical) developer_tools ca Frase en Anglès (o buit si és igual)
preferences developer_tools ca Preferències
preferences have been updated developer_tools ca Preferències actualitzades
project developer_tools ca Projecte
remove developer_tools ca Treure
removed %1 phrases from the target language, as they are not present in the source language! developer_tools ca Eliminades %1 frases de l'idioma origen, perquè no se troben en el llenguatge font!
returns to the application list, not saved changes get lost !!! developer_tools ca Torna a la llista d'aplicacions, els canvis no guardats es perdran !!!
revert developer_tools ca Revertir
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools ca Desa les traduccions afegides/canviades a un magatzem intern, per al seu ús en posteriors accions
search changelogs developer_tools ca Cercar en registres de canvis
search for missing phrase developer_tools ca Cercar per frase omesa
search new phrases developer_tools ca Cercar noves frases
searches the source-code for phrases not in the actual source-lang-file developer_tools ca Cerca en el codi font frases que no hi siguin al arxiu d'idioma actual
select project developer_tools ca Seleccionar projecte
sf project tracker developer_tools ca Seguiment de Projecte SF
sf project tracker preferences preferences ca Preferències de seguiment de Projecte SF
source language developer_tools ca Idioma Origen
sourceforge project id developer_tools ca Id. de projecte a Sourceforge
sourceforge project tracker developer_tools ca Seguiment de projecte Sourceforge
sourceforge project tracker preferences developer_tools ca Preferències de seguiment de projecte Sourceforge
step developer_tools ca Pas
submit developer_tools ca Enviar
target language developer_tools ca Idioma Destí
title developer_tools ca Títol
translate developer_tools ca Tradueix
translation developer_tools ca Traducció
translation of phrase developer_tools ca Traducció de frase
update developer_tools ca Actualitza
update database developer_tools ca Actualitza Base de Dades
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools ca Actualitza la traducció d'ambdós arxius d'idioma a la vostra base de dades, perquè pogueu verificar el vostre treball d'immediat
version developer_tools ca Versió
write developer_tools ca Escriure
write the lang-file to the apps setup-dir developer_tools ca Escriu l'arxiu d'idioma al directori "setup" de l'aplicació
write to lang table developer_tools ca Escriu a la taula d'idioma
writing langfile for '%1' ... developer_tools ca Escrivint arxiu d'idioma per a '%1' ...
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools ca Heu de [Desar] cada canvi manual als camps anteriors, abans de continuar amb el pas següent !!!
you must a version developer_tools ca Heu de versionar
you must enter a change developer_tools ca Heu d'entrar un canvi
you must select a project developer_tools ca Heu de sel·leccionar un projecte
you need to set your preferences for this app developer_tools ca Heu d'establir les vostres preferències per a aquesta aplicació

View File

@ -1,74 +0,0 @@
add developer_tools cs přidat
add change developer_tools cs Přidat změnu
add more developer_tools cs Přidat další
add new phrase developer_tools cs Přidat novou frázi
add phrase developer_tools cs přidat frázi
allows you to add a single phrase developer_tools cs Dovoluje přidat jednu frázi
application developer_tools cs Aplikace
back developer_tools cs Zpět
cancel developer_tools cs Storno
change developer_tools cs Změnit
changelog entry has been added developer_tools cs Záznam do změnového protokolu byl přidán
changelogs developer_tools cs Změnové protokoly
clears the internal buffer, all changes made sofar are lost developer_tools cs Vymaže interní buffer, všechny dosud provedené změny budou ztraceny
create new language file developer_tools cs Vytvořit nový jazykový soubor
create sgml file developer_tools cs Vytvořit SGML soubor
developer tools - preferences developer_tools cs Vývojářské nástroje - předvolby
developer_tools common cs Nástroje pro překlad
diary developer_tools cs Zápisník
done developer_tools cs hotovo
download developer_tools cs Stáhnout
download the lang-file to be saved in the apps setup-dir developer_tools cs Stáhnout jazykový soubor pro uložení do setup složky aplikace
edit developer_tools cs Editovat
installed applications developer_tools cs Instalované aplikace
language file management developer_tools cs Správa jazykových souborů
list changelogs developer_tools cs Zobrazit změnové protokoly
load developer_tools cs Nahrát
loading source langfile developer_tools cs Nahrávám zdrojový jazykový soubor
loading target langfile developer_tools cs Nahrávám cílový jazykový soubor
loads the selected lang-files, to be modified in the next steps developer_tools cs Nahraje vybrané jazykové soubory pro jejich úpravu v následujících krocích
message developer_tools cs Zpráva
message_id in english developer_tools cs id zprávy v angličtině
no file developer_tools cs žádný soubor
ok developer_tools cs OK
original developer_tools cs Originál
phrase in english (or empty if identical) developer_tools cs Fráze v angličtině (prázdné, je-li identická)
preferences developer_tools cs Předvolby
preferences have been updated developer_tools cs Předvolby byly zaktualizovány
project developer_tools cs Projekt
remove developer_tools cs Odstranit
removed %1 phrases from the target language, as they are not present in the source language! developer_tools cs Odstraněno %1 frází z cílového jazykového souboru, které nebyly ve zdrojovém jazykovém souboru
returns to the application list, not saved changes get lost !!! developer_tools cs Návrat do seznamu aplikací, neuložené změny budou ztraceny !!!
revert developer_tools cs Vrátit zpět
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools cs Uloží přidané/změněné překlady do interního bufferu, aby mohly být použity v dalších krocích
search changelogs developer_tools cs Prohledat změnový protokol
search for missing phrase developer_tools cs Hledat chybějící fráze
search new phrases developer_tools cs Hledat nové fráze
searches the source-code for phrases not in the actual source-lang-file developer_tools cs Hledá ve zdrojovém kódu aplikace fráze, které nejsou v aktuálním zdrojovém jazykovém souboru
select project developer_tools cs Vybrat projekt
sf project tracker developer_tools cs SF Sledování projektu
sf project tracker preferences preferences cs SF Předvolby sledování projektu
source language developer_tools cs Zdrojový jazyk
sourceforge project id developer_tools cs Projekt ID na Sourceforge
sourceforge project tracker developer_tools cs Sourceforge sledování projektu
sourceforge project tracker preferences developer_tools cs Sourceforge předvolby sledování projektu
step developer_tools cs Krok
submit developer_tools cs Odeslat
target language developer_tools cs Cílový jazyk
title developer_tools cs Název
translate developer_tools cs Přeložit
translation developer_tools cs Překlad
translation of phrase developer_tools cs Překlad fráze
update developer_tools cs Aktualizovat
update database developer_tools cs Aktualizovat databázi
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools cs Zaktualizuje překlady obou jazykových souborů v databázi, takže můžete svou práci ihned zkontrolovat
version developer_tools cs Verze
write developer_tools cs Uložit
write the lang-file to the apps setup-dir developer_tools cs Uložit jazykový soubor do setup složky aplikace
write to lang table developer_tools cs Uložit do jazykové tabulky
writing langfile for '%1' ... developer_tools cs Ukládám jazykový soubor pro '%1' ...
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools cs Musíte [Uložit] každou změnu ve výše zobrazených polích než budete moci pokračovat dalším krokem !!!
you must a version developer_tools cs Musíte verzi
you must enter a change developer_tools cs Musíte zadat změnu
you must select a project developer_tools cs Musíte vybrat projekt
you need to set your preferences for this app developer_tools cs Musíte nastavit své předvolby pro tuto aplikaci

View File

@ -1,74 +0,0 @@
add developer_tools da tilføj
add change developer_tools da Tilføj ændring
add more developer_tools da Tilføj mere
add new phrase developer_tools da Tilføj en ny sætning
add phrase developer_tools da tilføj sætning
allows you to add a single phrase developer_tools da Tillader at tilføje en sætning
application developer_tools da Applikation
back developer_tools da Tilbage
cancel developer_tools da Annuller
change developer_tools da Ændre
changelog entry has been added developer_tools da Journal-log notat er tilføjet
changelogs developer_tools da Journal-logs
clears the internal buffer, all changes made sofar are lost developer_tools da Tømmer den interne buffer, alle ændringer laver indtil nu er tabt
create new language file developer_tools da Opret en ny sprog fil
create sgml file developer_tools da Opret SGML fil
developer tools - preferences developer_tools da Udvikler værktøj - præferencer
developer_tools common da Oversætter værktøj
diary developer_tools da Dagbog
done developer_tools da gjort
download developer_tools da Hent
download the lang-file to be saved in the apps setup-dir developer_tools da Hent lang-filen som er gemt i applikationens setup bibliotek
edit developer_tools da Redigér
installed applications developer_tools da Har installeret applikationer
language file management developer_tools da Sprog fil håndtering
list changelogs developer_tools da Vis Journal-logs
load developer_tools da Indlæs
loading source langfile developer_tools da Indlæst kilde sprog fil
loading target langfile developer_tools da Indlæst destination sprog fil
loads the selected lang-files, to be modified in the next steps developer_tools da Indlæser den valgte lang-fil, som skal ændres i de næste trin
message developer_tools da Besked
message_id in english developer_tools da besked_id på engelsk
no file developer_tools da ingen fil
ok developer_tools da ok
original developer_tools da Orginal
phrase in english (or empty if identical) developer_tools da Sætning på engelsk (tom hvis identisk)
preferences developer_tools da Præferencer
preferences have been updated developer_tools da Præferencerne er opdateret
project developer_tools da Projekt
remove developer_tools da Fjern
removed %1 phrases from the target language, as they are not present in the source language! developer_tools da Har fjernet %1 sætninger fra target sproget da disse sætninger ikke er med i source sproget!
returns to the application list, not saved changes get lost !!! developer_tools da Returnerer til applikations listen, ikke gemte ændringer vil være tabt!!!
revert developer_tools da Gendan
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools da Gemmer de tilføjet/ændrede oversættelser til en intern buffer, for at blive brugt i de næste trin
search changelogs developer_tools da Søg Journal-logs
search for missing phrase developer_tools da Søg efter manglende sætninger
search new phrases developer_tools da Søg nye sætninger
searches the source-code for phrases not in the actual source-lang-file developer_tools da Søger i kilde koden for sætninger der ikke er i kilde lang-filen
select project developer_tools da Vælg projekt
sf project tracker developer_tools da SF Project tracker
sf project tracker preferences preferences da SF Project tracker præferencer
source language developer_tools da Kilde sprog
sourceforge project id developer_tools da Sourceforge projekt ID
sourceforge project tracker developer_tools da Sourceforge project tracker
sourceforge project tracker preferences developer_tools da Sourceforge project tracker præferencer
step developer_tools da Trin
submit developer_tools da Gem
target language developer_tools da Destination sprog
title developer_tools da Titel
translate developer_tools da Oversæt
translation developer_tools da Oversættelse
translation of phrase developer_tools da Oversættelse af sætning
update developer_tools da Opdater
update database developer_tools da Opdater database
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools da Opdaterer oversættelserne af begge lang-filer i din database, så du kan verificere dit arbejde straks
version developer_tools da Version
write developer_tools da Skriv
write the lang-file to the apps setup-dir developer_tools da Skriv sprog filen til applikationens setup bibliotek
write to lang table developer_tools da Skriv til lang tabel
writing langfile for '%1' ... developer_tools da Skriver sprog filen '%1'....
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools da !!! Du skal [gem] alle manuelle ændringer i overstående felter, før du kan gå videre til næste trin !!!
you must a version developer_tools da Du skal indtaste en version
you must enter a change developer_tools da Du skal indtaste en ændring
you must select a project developer_tools da Du skal vælge et projekt
you need to set your preferences for this app developer_tools da Du skal sætte dine præferencer for denne applikation

View File

@ -1,74 +0,0 @@
add developer_tools de Zufügen
add change developer_tools de Änderung zufügen
add more developer_tools de Weitere zufügen
add new phrase developer_tools de Neuer Text
add phrase developer_tools de Text zufügen
allows you to add a single phrase developer_tools de Erlaubt einen einzelnen Text zuzufügen
application developer_tools de Anwendung
back developer_tools de Zurück
cancel developer_tools de Abbruch
change developer_tools de Ändern
changelog entry has been added developer_tools de Änderungslog Eintrag wurde zugefügt
changelogs developer_tools de Änderungslog
clears the internal buffer, all changes made sofar are lost developer_tools de Löscht den internen Speicher, alle bisherigen Änderungen gehen verloren
create new language file developer_tools de Neue Sprachdatei erzeugen
create sgml file developer_tools de SGML Datei erzeugen
developer tools - preferences developer_tools de Entwicklerwerkzeuge - Einstellungen
developer_tools common de Übersetzungswerkzeuge
diary developer_tools de Tagebuch
done developer_tools de Fertig
download developer_tools de Download
download the lang-file to be saved in the apps setup-dir developer_tools de Download der Übersetzungsdatei, um sie im Setup-Verzeichnis der Anwendung zu speichern
edit developer_tools de Bearbeiten
installed applications developer_tools de Installierte Anwendungen
language file management developer_tools de Sprachdateiverwaltung
list changelogs developer_tools de Änderungslogs anzeigen
load developer_tools de Laden
loading source langfile developer_tools de Quell-Sprachdatei laden
loading target langfile developer_tools de Ziel-Sprachdatei laden
loads the selected lang-files, to be modified in the next steps developer_tools de Lädt die ausgewählten Sprachen, um sie in den nächsten Schritten zu bearbeiten
message developer_tools de Text
message_id in english developer_tools de Text-Schlüssel in Englisch
no file developer_tools de keine Datei
ok developer_tools de Ok
original developer_tools de Original
phrase in english (or empty if identical) developer_tools de Text in Englisch (oder leer wenn identisch)
preferences developer_tools de Einstellungen
preferences have been updated developer_tools de Einstellungen wurden geschrieben
project developer_tools de Projekt
remove developer_tools de Entfernen
removed %1 phrases from the target language, as they are not present in the source language! developer_tools de %1 Phrasen der Zielsprache entfernt die nicht in der Quellsprache vorhanden sind!
returns to the application list, not saved changes get lost !!! developer_tools de Kehrt zur Liste der Anwendungen zurück, nicht gespeicherte Änderungen gehen verloren !!!
revert developer_tools de Rückgängig machen
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools de Speichert die zugefügten/geänderten Übersetzungen intern, für die weiteren Schritte
search changelogs developer_tools de Änderungslog durchsuchen
search for missing phrase developer_tools de fehlende Texte suchen
search new phrases developer_tools de Neue Texte suchen
searches the source-code for phrases not in the actual source-lang-file developer_tools de Durchsucht den Quellcode nach neuen Texten die noch nicht in der Quell-Datei sind
select project developer_tools de Projekt auswählen
sf project tracker developer_tools de SF Projekt Tracker
sf project tracker preferences preferences de SF Projekt Tracker Einstellungen
source language developer_tools de Quell-Sprache
sourceforge project id developer_tools de Sourceforge Projekt-ID
sourceforge project tracker developer_tools de Sourceforge Projekt Tracker
sourceforge project tracker preferences developer_tools de Sourceforge Projekt Tracker Einstellungen
step developer_tools de Schritt
submit developer_tools de Übertragen
target language developer_tools de Ziel-Sprache
title developer_tools de Titel
translate developer_tools de Übersetzen
translation developer_tools de Übersetzung
translation of phrase developer_tools de Übersetzung des Textes
update developer_tools de Schreiben
update database developer_tools de Datenbank aktualisieren
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools de Aktualisiert die Übersetzungen für beide Sprachen in Ihrer Datenbank, damit Sie Ihre Arbeit sofort überprüfen können
version developer_tools de Version
write developer_tools de Schreiben
write the lang-file to the apps setup-dir developer_tools de Schreibt die Übersetzungsdatei in das Setup-Verzeichnis der Anwendung
write to lang table developer_tools de Datenbank schreiben
writing langfile for '%1' ... developer_tools de Sprachdatei für '%1' schreiben ...
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools de !!! Sie müssen nach jeder manuellen Änderung in den obigen Feldern [Speichern], bevor sie zum nächsten Schritt weitergehen !!!
you must a version developer_tools de Sie benötigen eine Version
you must enter a change developer_tools de Sie müssen eine Änderungen eingeben
you must select a project developer_tools de Sie müssen ein Projekt auswählen
you need to set your preferences for this app developer_tools de Sie müssen Ihre Einstellungen für diese Anwendung setzen

View File

@ -1,74 +0,0 @@
add developer_tools en Add
add change developer_tools en Add change
add more developer_tools en Add more
add new phrase developer_tools en Add new phrase
add phrase developer_tools en Add phrase
allows you to add a single phrase developer_tools en Allows you to add a single phrase
application developer_tools en Application
back developer_tools en Back
cancel developer_tools en Cancel
change developer_tools en Change
changelog entry has been added developer_tools en Changelog entry has been added.
changelogs developer_tools en Changelogs
clears the internal buffer, all changes made sofar are lost developer_tools en Clears the internal buffer, all changes made so far are lost
create new language file developer_tools en Create new language file
create sgml file developer_tools en Create SGML file
developer tools - preferences developer_tools en Developer tools - preferences
developer_tools common en Translation Tools
diary developer_tools en Diary
done developer_tools en Done
download developer_tools en Download
download the lang-file to be saved in the apps setup-dir developer_tools en Download the language file to be saved in the apps setup-dir
edit developer_tools en Edit
installed applications developer_tools en Installed applications
language file management developer_tools en Language file management
list changelogs developer_tools en List changelogs
load developer_tools en Load
loading source langfile developer_tools en Loading source langfile
loading target langfile developer_tools en Loading target langfile
loads the selected lang-files, to be modified in the next steps developer_tools en Loads the selected lang-files to be modified in the next steps
message developer_tools en Message
message_id in english developer_tools en message_id in English
no file developer_tools en No file
ok developer_tools en Ok
original developer_tools en Original
phrase in english (or empty if identical) developer_tools en Phrase in English, or empty if identical
preferences developer_tools en Preferences
preferences have been updated developer_tools en Preferences have been updated.
project developer_tools en Project
remove developer_tools en Remove
removed %1 phrases from the target language, as they are not present in the source language! developer_tools en Removed %1 phrases from the target language as they are not present in the source language!
returns to the application list, not saved changes get lost !!! developer_tools en Returns to the application list, not saved changes get lost!
revert developer_tools en Revert
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools en Saves the added/changed translations to an internal buffer, to be used in further steps
search changelogs developer_tools en Search changelogs
search for missing phrase developer_tools en Search for missing phrase
search new phrases developer_tools en Search new phrases
searches the source-code for phrases not in the actual source-lang-file developer_tools en Searches the source code for phrases not in the actual source lang file
select project developer_tools en Select project
sf project tracker developer_tools en SF project tracker
sf project tracker preferences preferences en SF project tracker preferences
source language developer_tools en Source language
sourceforge project id developer_tools en Sourceforge project ID
sourceforge project tracker developer_tools en Sourceforge project tracker
sourceforge project tracker preferences developer_tools en Sourceforge project tracker preferences
step developer_tools en Step
submit developer_tools en Submit
target language developer_tools en Target language
title developer_tools en Title
translate developer_tools en Translate
translation developer_tools en Translation
translation of phrase developer_tools en Translation of phrase
update developer_tools en Update
update database developer_tools en Update database
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools en Updates the translations of both lang files in your database, so you can verify your work immediately.
version developer_tools en Version
write developer_tools en Write
write the lang-file to the apps setup-dir developer_tools en Write the lang file to the apps setup-dir
write to lang table developer_tools en Write to lang table
writing langfile for '%1' ... developer_tools en Writing langfile for '%1' ...
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools en You have to [Save] every manual change in the above fields, before you can go to the next step!
you must a version developer_tools en You must a version
you must enter a change developer_tools en You must enter a change.
you must select a project developer_tools en You must select a project.
you need to set your preferences for this app developer_tools en You need to set your preferences for this app!

View File

@ -1,74 +0,0 @@
add developer_tools es-es añadir
add change developer_tools es-es Añadir cambio
add more developer_tools es-es Añadir más
add new phrase developer_tools es-es Añadir frase nueva
add phrase developer_tools es-es añadir frase
allows you to add a single phrase developer_tools es-es Le permite añadir una sola frase
application developer_tools es-es Aplicación
back developer_tools es-es Volver
cancel developer_tools es-es Cancelar
change developer_tools es-es Cambiar
changelog entry has been added developer_tools es-es Se ha añadido una entrada de registro de cambios
changelogs developer_tools es-es Registros de cambios
clears the internal buffer, all changes made sofar are lost developer_tools es-es Vacía el búfer interno, perdiendo los cambios realizados
create new language file developer_tools es-es Crea un nuevo fichero de idioma
create sgml file developer_tools es-es Crear fichero SGML
developer tools - preferences developer_tools es-es Herramientas de desarrollo - Preferencias
developer_tools common es-es Herramientas de traducción
diary developer_tools es-es Diario
done developer_tools es-es Hecho
download developer_tools es-es Descargar
download the lang-file to be saved in the apps setup-dir developer_tools es-es Descargar el fichero de idioma que hay que guardar en el directorio de configuración de las aplicaciones
edit developer_tools es-es Editar
installed applications developer_tools es-es Aplicaciones instaladas
language file management developer_tools es-es Gestión de ficheros de idioma
list changelogs developer_tools es-es Lista del registro de cambios
load developer_tools es-es Cargar
loading source langfile developer_tools es-es Cargando fichero de idioma de origen
loading target langfile developer_tools es-es Cargando fichero de idioma de destino
loads the selected lang-files, to be modified in the next steps developer_tools es-es Carga los ficheros de idioma seleccionados, para modificar en los pasos posteriores
message developer_tools es-es Mensaje
message_id in english developer_tools es-es id del mensaje en inglés
no file developer_tools es-es sin fichero
ok developer_tools es-es Aceptar
original developer_tools es-es Original
phrase in english (or empty if identical) developer_tools es-es Frase en inglés (o en blanco si son idénticas)
preferences developer_tools es-es Preferencias
preferences have been updated developer_tools es-es Se han actualizado las preferencias
project developer_tools es-es Proyecto
remove developer_tools es-es Borrar
removed %1 phrases from the target language, as they are not present in the source language! developer_tools es-es Se han borrado %1 frases del idioma de destino, ya que ya no están presentes en el idioma de origen
returns to the application list, not saved changes get lost !!! developer_tools es-es Vuelve a la lista de aplicaciones. Se perderán los cambios que se hayan guardado.
revert developer_tools es-es Volver
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools es-es Guarda las traducciones añadidas o modificadas a un búfer interno, para usar en los pasos siguientes
search changelogs developer_tools es-es Buscar en el registro de cambios
search for missing phrase developer_tools es-es Buscar una frase que falta
search new phrases developer_tools es-es Buscar frases nuevas
searches the source-code for phrases not in the actual source-lang-file developer_tools es-es Busca en el código fuente frases que no están en el fichero de idioma actual
select project developer_tools es-es Seleccionar proyecto
sf project tracker developer_tools es-es Proyecto de seguimiento SF
sf project tracker preferences preferences es-es Preferencias del proyecto de seguimiento SF
source language developer_tools es-es Idioma de origen
sourceforge project id developer_tools es-es ID del proyecto en Sourceforge
sourceforge project tracker developer_tools es-es Proyecto de seguimiento en Sourceforge
sourceforge project tracker preferences developer_tools es-es Preferencias del proyecto de seguimiento en Sourceforge
step developer_tools es-es Paso
submit developer_tools es-es Enviar
target language developer_tools es-es Idioma de destino
title developer_tools es-es Título
translate developer_tools es-es Traducir
translation developer_tools es-es Traducción
translation of phrase developer_tools es-es Traducción de la frase
update developer_tools es-es Actualizar
update database developer_tools es-es Actualizar base de datos
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools es-es Actualiza las traducciones ambos ficheros de idiomas en la base de datos, para poder comprobar los resultados inmediatamente
version developer_tools es-es Versión
write developer_tools es-es Escribir
write the lang-file to the apps setup-dir developer_tools es-es Escribir el fichero de idioma en el directorio de configuración de aplicaciones
write to lang table developer_tools es-es Escribir en la tabla de idioma
writing langfile for '%1' ... developer_tools es-es Escribiendo fichero de idioma para "%1"
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools es-es ¡¡Tiene que [Grabar] todos los cambios realizados en los campos de arriba, antes de ir al siguiente paso!!
you must a version developer_tools es-es Debe introducir una versión
you must enter a change developer_tools es-es Debe introducir un cambio
you must select a project developer_tools es-es Debe seleccionar un proyecto
you need to set your preferences for this app developer_tools es-es Necesita establecer las preferencias para esta aplicación

View File

@ -1,63 +0,0 @@
add developer_tools et lisa
add change developer_tools et Lisa muuda
add more developer_tools et Lisa rohkem
add new phrase developer_tools et Lisa uus fraas
add phrase developer_tools et lisa fraas
allows you to add a single phrase developer_tools et Lubab sul lisada üksiku fraasi
application developer_tools et Rakendus
back developer_tools et Tagasi
cancel developer_tools et Tühista
change developer_tools et Muuda
changelogs developer_tools et Muudatustelogid
create new language file developer_tools et Tee uus keelefail
create sgml file developer_tools et Tee SGML fail
developer tools - preferences developer_tools et Arendaja tööriistade - eelistused
developer_tools common et Tõlkimise tööriistad
done developer_tools et valmis
download developer_tools et Lae alla
edit developer_tools et Muuda
installed applications developer_tools et Installeeritud rakendused
language file management developer_tools et Keelefaili manageerimine
list changelogs developer_tools et Muutustelogide nimekiri
load developer_tools et Lae
loading source langfile developer_tools et Laen algkeele
loading target langfile developer_tools et Laen sihtkeele
message developer_tools et Sõnum
message_id in english developer_tools et teate_id Eesti keeles
no file developer_tools et pole faili
ok developer_tools et ok
original developer_tools et Originaal
phrase in english (or empty if identical) developer_tools et Fraas Eestikeeles (või jäta tühjaks kui identne)
preferences developer_tools et Eelistused
preferences have been updated developer_tools et Eelistused on uuendatud
project developer_tools et Projekt
remove developer_tools et Eemalda
removed %1 phrases from the target language, as they are not present in the source language! developer_tools et Eemaldatud %1 fraasi sihtkeelest, kuna neid ei esine algkeeles!
revert developer_tools et Võta tagasi
search changelogs developer_tools et Otsi muutustelogisid
search for missing phrase developer_tools et Otsi puuduvaid fraase
search new phrases developer_tools et Otsi uusi fraase
searches the source-code for phrases not in the actual source-lang-file developer_tools et Otsib fraase lähtegoodist mida pole käesolevas alg-keele-failis
select project developer_tools et Vali projekt
sf project tracker developer_tools et SF Projekti jälgija
sf project tracker preferences preferences et SF Projekti jälgija eelisstused
source language developer_tools et Algkeel
sourceforge project id developer_tools et Sourceforge projekti ID
sourceforge project tracker developer_tools et Sourceforge projekti jälgija
sourceforge project tracker preferences developer_tools et Sourceforge projekti jälgija eelisstused
step developer_tools et Samm
submit developer_tools et Saada
target language developer_tools et Sihtkeel
title developer_tools et Pealkiri
translate developer_tools et Tõlgi
translation developer_tools et Tõlkimine
update developer_tools et Uuenda
update database developer_tools et Uuuenda Andmebaasi
version developer_tools et Versioon
write developer_tools et Kirjuta
write the lang-file to the apps setup-dir developer_tools et Kirjuta keelefail rakenduste kausta
write to lang table developer_tools et Kirjuta keele fail
writing langfile for '%1' ... developer_tools et Kirjutan keelefaili '%1' ...
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools et Sa pead Salvestama kõik käsitsi tehtud muudatused üleval väljades enne kui saad minna järgmise sammujuurde !!!
you must select a project developer_tools et Pead valima projekti
you need to set your preferences for this app developer_tools et Vajalik on seada eelistused selle rakendusejaoks

View File

@ -1,5 +0,0 @@
download developer_tools eu Deskargatu
installed applications developer_tools eu Aplikazioak instalatuta
no file developer_tools eu ez dago fitxategirik
remove developer_tools eu ezabatu
translation developer_tools eu Itzulpena

View File

@ -1,64 +0,0 @@
add developer_tools fa اضافه کردن
add change developer_tools fa اضافه کردن تغییرات
add more developer_tools fa اضافه کردن بیشتر
add new phrase developer_tools fa اضافه کردن عبارت جدید
add phrase developer_tools fa اضافه کردن عبارت
allows you to add a single phrase developer_tools fa به شما اجازه می دهد که یک عبارت جدید اضافه کنید
application developer_tools fa برنامه
back developer_tools fa بازگشت
cancel developer_tools fa لغو
change developer_tools fa تغییر
changelog entry has been added developer_tools fa ثبت تغییرات اضافه شد
changelogs developer_tools fa ثبتهای تغییرات
create new language file developer_tools fa ایجاد پرنده زبان جدید
create sgml file developer_tools fa ایجاد پرونده SGML جدید
developer tools - preferences developer_tools fa تنظیمات ابزارهای توسعه دهندگان
developer_tools common fa ابزارهای ترجمه
done developer_tools fa انجام شد
download developer_tools fa دریافت
download the lang-file to be saved in the apps setup-dir developer_tools fa دریافت پرونده زبان برای قراردادن در پوشه برپاسازی برنامه
edit developer_tools fa ویراستن
installed applications developer_tools fa برنامه های نصب شده
language file management developer_tools fa مدیریت پرونده زبان
list changelogs developer_tools fa لیست ثبت تغییرات
load developer_tools fa بارگذاری
loading source langfile developer_tools fa بارگذاری پرونده زبان مبدأ
loading target langfile developer_tools fa بارگذاری پرونده زبان مقصد
loads the selected lang-files, to be modified in the next steps developer_tools fa پرونده زبان انتخاب شده را برای ترجمه در مرحله بعد بارگذاری می کند
message developer_tools fa پیام
message_id in english developer_tools fa کد پیام به انگلیسی
no file developer_tools fa پرونده ای نیست
ok developer_tools fa تأیید
original developer_tools fa اصلی
phrase in english (or empty if identical) developer_tools fa عبارت به انگلیسی
preferences developer_tools fa تنظیمات
preferences have been updated developer_tools fa تنظیمات به روز شد
project developer_tools fa پروژه
remove developer_tools fa حذف
revert developer_tools fa برگرداندن
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools fa ترجمه های انجام شده را در یک بافر داخلی ذخیره میکند تا در مرحله بعدی استفاده شود
search changelogs developer_tools fa جستجوی ثبت تغییرات
search for missing phrase developer_tools fa جستجو برای عبارت گم شده
search new phrases developer_tools fa جستجو برای عبارت جدید
searches the source-code for phrases not in the actual source-lang-file developer_tools fa کد منبع را برای عبارتی که در پرونده زبان موجود نیست جستجو می کند
select project developer_tools fa جستجوی پروژه
source language developer_tools fa زبان مبدأ
step developer_tools fa مرحله
submit developer_tools fa ثبت
target language developer_tools fa زبان مقصد
title developer_tools fa عنوان
translate developer_tools fa ترجمه
translation developer_tools fa ترجمه
translation of phrase developer_tools fa ترجمه عبارت
update developer_tools fa به روز
update database developer_tools fa به روز کردن پایگاه داده
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools fa پایگاه داده را فورا به روز می کند و شما می توانید نتیجه کارتان را ببینید
version developer_tools fa نسخه
write developer_tools fa نوشتن
write the lang-file to the apps setup-dir developer_tools fa نوشتن پرونده زبان در پوشه برنامه برپا سازی
write to lang table developer_tools fa نوشتن در جدول زبان
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools fa شما باید هر تغییراتی که در فیلدهای بالا انجام داده اید ذخیره کنید تا بتوانید به مرحله بعد بروید
you must a version developer_tools fa شما باید یک نسخه باشید
you must enter a change developer_tools fa شما باید تغییراتی وارد کنید
you must select a project developer_tools fa شما باید پروژه ای انتخاب کنید
you need to set your preferences for this app developer_tools fa شما نیاز دارید که تنظیمات خود را برای برنامه مورد نظر انجام دهید

View File

@ -1,74 +0,0 @@
add developer_tools fi Lisää
add change developer_tools fi Lisää muutos
add more developer_tools fi Lisää enemmän
add new phrase developer_tools fi Uusi fraasi
add phrase developer_tools fi Lisää fraasi
allows you to add a single phrase developer_tools fi Lisää yksi fraasi
application developer_tools fi Sovellus
back developer_tools fi Takaisin
cancel developer_tools fi Peruuta
change developer_tools fi Muuta
changelog entry has been added developer_tools fi Kirjaus muutoslokiin tehty
changelogs developer_tools fi Muutoslokit
clears the internal buffer, all changes made sofar are lost developer_tools fi Tyhjentää sisäisen puskurin, tähän asti tekemäsi muutokset poistuvat
create new language file developer_tools fi Uusi kielitiedosto
create sgml file developer_tools fi Uusi SGML -tiedosto
developer tools - preferences developer_tools fi Kehittäjän työkalut - asetukset
developer_tools common fi Käännöstyökalu
diary developer_tools fi Päiväkirja
done developer_tools fi Valmis
download developer_tools fi Lataa
download the lang-file to be saved in the apps setup-dir developer_tools fi Lataa kielitiedosto tallennettavaksi sovelluksen setup -hakemistoon
edit developer_tools fi Muokkaa
installed applications developer_tools fi Asennetut sovellukset
language file management developer_tools fi Kielitiedostojen hallinta
list changelogs developer_tools fi Listaa muutoslokit
load developer_tools fi Lataa
loading source langfile developer_tools fi Ladataan lähdekielen kielitiedostoa
loading target langfile developer_tools fi Ladataan kohdekielen kielitiedostoa
loads the selected lang-files, to be modified in the next steps developer_tools fi Lataa valitut kielitiedostot muokattaviksi seuraavassa vaiheessa
message developer_tools fi Viesti
message_id in english developer_tools fi message_id (englanniksi)
no file developer_tools fi Ei tiedostoa
ok developer_tools fi OK
original developer_tools fi Alkuperäinen
phrase in english (or empty if identical) developer_tools fi Fraasi englanniksi (tai tyhjä jos sama)
preferences developer_tools fi Asetukset
preferences have been updated developer_tools fi Asetukset päivitetty
project developer_tools fi Projekti
remove developer_tools fi Poista
removed %1 phrases from the target language, as they are not present in the source language! developer_tools fi Poistettu %1 fraasi kohdekielestä, koska sitä ei löydy lähdekielestä!
returns to the application list, not saved changes get lost !!! developer_tools fi Palaa takaisin sovellusluetteloon, tallentamattomat muutokset menetetään !!!!
revert developer_tools fi Hylkää muutokset
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools fi Tallentaa lisätyt/muuttuneet käännökset sisäiseen puskuriin käytettäviksi seuraavassa vaiheessa
search changelogs developer_tools fi Etsi muutoslokeista
search for missing phrase developer_tools fi Etsi puuttuvat fraasit
search new phrases developer_tools fi Etsi uusia fraaseja
searches the source-code for phrases not in the actual source-lang-file developer_tools fi Etsi lähdekoodista lähdekielitiedostosta puuttuvia fraaseja
select project developer_tools fi Valitse projekti
sf project tracker developer_tools fi SF projektinseuranta
sf project tracker preferences preferences fi SF projektinseurannan asetukset
source language developer_tools fi Lähdekieli
sourceforge project id developer_tools fi Sourceforge projekti-ID
sourceforge project tracker developer_tools fi Sourceforge projektinseuranta
sourceforge project tracker preferences developer_tools fi Sourceforge projektinseurannan asetukset
step developer_tools fi Vaihe
submit developer_tools fi Lähetä
target language developer_tools fi Kohdekieli
title developer_tools fi Otsikko
translate developer_tools fi Käännä
translation developer_tools fi Käännös
translation of phrase developer_tools fi Fraasin käännös
update developer_tools fi Päivitä
update database developer_tools fi Päivitä tietokanta
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools fi Päivittää molemmista kielitiedostoista ladatut käännökset tietokantaan, jolloin näet lopputuloksen heti.
version developer_tools fi Versio
write developer_tools fi Kirjoita
write the lang-file to the apps setup-dir developer_tools fi Kirjoita kielitiedosto sovelluksen setup -kansioon
write to lang table developer_tools fi Kirjoita kielitiedostoon
writing langfile for '%1' ... developer_tools fi Kirjoitetaan kielitiedostoa '%1' ...
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools fi Jos teit muutoksia, muista painaa [Tallenna] ennen kuin jatkat !!!
you must a version developer_tools fi Anna versio
you must enter a change developer_tools fi Anna muutos
you must select a project developer_tools fi Valitse projekti
you need to set your preferences for this app developer_tools fi Tarkasta sovelluksen asetukset

View File

@ -1,74 +0,0 @@
add developer_tools fr Ajouter
add change developer_tools fr Ajouter la modification
add more developer_tools fr Ajouter encore
add new phrase developer_tools fr Ajouter une nouvelle phrase
add phrase developer_tools fr ajouter la phrase
allows you to add a single phrase developer_tools fr Vous permet d'ajouter une phrase
application developer_tools fr Application
back developer_tools fr Retour
cancel developer_tools fr Annuler
change developer_tools fr Changer
changelog entry has been added developer_tools fr L'entrée a été ajoutée dans le journal des changements
changelogs developer_tools fr Journaux de changements
clears the internal buffer, all changes made sofar are lost developer_tools fr Vide le tampon interne, tous les changements faits jusqu'ici sont perdus
create new language file developer_tools fr Créer un Nouveau Fichier de Langue
create sgml file developer_tools fr Créer un fichier SGML
developer tools - preferences developer_tools fr Outils développeurs - préférences
developer_tools common fr Outils de traduction
diary developer_tools fr Journal
done developer_tools fr fait
download developer_tools fr Télécharger
download the lang-file to be saved in the apps setup-dir developer_tools fr Télécharger le fichier de langue pour qu'il soit enregistré dans le répertoire setup de l'application
edit developer_tools fr Editer
installed applications developer_tools fr Applications installées
language file management developer_tools fr Gestion des fichiers de langue
list changelogs developer_tools fr Lister les journaux de changements
load developer_tools fr Charger
loading source langfile developer_tools fr Charge le fichier de langue source
loading target langfile developer_tools fr Charge le fichier de langue destination
loads the selected lang-files, to be modified in the next steps developer_tools fr Charge les fichiers de langue sélectionnés afin qu'ils soient modifiés dans les prochaines étapes
message developer_tools fr Message
message_id in english developer_tools fr message_id en Anglais
no file developer_tools fr pas de fichier
ok developer_tools fr ok
original developer_tools fr Original
phrase in english (or empty if identical) developer_tools fr Phrase en Anglais (ou rien si identique)
preferences developer_tools fr Préférences
preferences have been updated developer_tools fr Les préférences ont été mises à jour
project developer_tools fr Projet
remove developer_tools fr Enlever
removed %1 phrases from the target language, as they are not present in the source language! developer_tools fr Enlevé %1 phrases de la langue de destination car elles sont absentes de la langue source!
returns to the application list, not saved changes get lost !!! developer_tools fr Retourne à la liste des applications, les changements non enregistrés seront perdus !!!
revert developer_tools fr Revenir
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools fr Enregistre les traductions ajoutées/modifiées dans un tampon interne afin qu'elles puissent être utilisées dans les étapes suivantes
search changelogs developer_tools fr Chercher les journaux de changements
search for missing phrase developer_tools fr Chercher les phrases manquantes
search new phrases developer_tools fr Rechercher les nouvelles phrases
searches the source-code for phrases not in the actual source-lang-file developer_tools fr Recherche dans le code source les phrases non présentes dans le fichier de langue source actuel
select project developer_tools fr Choisir un projet
sf project tracker developer_tools fr traceur de projet SF
sf project tracker preferences preferences fr Préférences du traceur de projet SF
source language developer_tools fr Langue source
sourceforge project id developer_tools fr ID de projet Sourceforge
sourceforge project tracker developer_tools fr traceur de projet Sourceforge
sourceforge project tracker preferences developer_tools fr Préférences du traceur de projets Sourceforge
step developer_tools fr Etape
submit developer_tools fr Soumettre
target language developer_tools fr Langue destination
title developer_tools fr Titre
translate developer_tools fr Traduire
translation developer_tools fr Traduction
translation of phrase developer_tools fr Traduction de la phrase
update developer_tools fr Mettre à jour
update database developer_tools fr Mettre à jour la base de données
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools fr Met à jour les traductions des deux fichiers de langue dans votre base de données, que vous puissiez vérifier votre travail immédiatement
version developer_tools fr Version
write developer_tools fr Ecrire
write the lang-file to the apps setup-dir developer_tools fr Ecrit le fichier de langue dans le répertoire setup de l'application
write to lang table developer_tools fr Ecrire dans la table de langue
writing langfile for '%1' ... developer_tools fr Mise à jour fichier de langue pour '%1' ...
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools fr Vous devez [Enregistrer] tout changement manuel dans les champs ci-dessus, avant de pouvoir aller à l'étape suivante !!!
you must a version developer_tools fr Vous devez une version
you must enter a change developer_tools fr Vous devez entrer une modification
you must select a project developer_tools fr Vous devez choisir un projet
you need to set your preferences for this app developer_tools fr Vous devez régler vos préférences pour cette application

View File

@ -1,19 +0,0 @@
add developer_tools hi जमा करो
add change developer_tools hi परिवर्तनो को मिलाना
add more developer_tools hi और् जमा करो
add new phrase developer_tools hi नये पद को मिलाना
add phrase developer_tools hi नये पद मिलाना
allows you to add a single phrase developer_tools hi नये पद को मिलाने कि अज्न डेटि है
application developer_tools hi कम्प्युटर प्रोग्राम
back developer_tools hi पीचे
cancel developer_tools hi रद्दा कर्ना
change developer_tools hi परिवर्तन्
changelog entry has been added developer_tools hi चन्गेलोग् एन्ट्र्य् को मिलाय गया है
changelogs developer_tools hi चन्गेलोग्स्
clears the internal buffer, all changes made sofar are lost developer_tools hi इन्टेर्नल् बुफ़्फ़ेर्स् कि सफई कर्ति है, सभि पर्वर्तने खोजयेन्गे
create new language file developer_tools hi नयि भाषा कि फ़िले को बनाना
create sgml file developer_tools hi एस् जि एम् एल् फ़िले को बनाना
developer tools - preferences developer_tools hi डेवेलोपेर् टूल्स् - प्रेफ़रेन्सेस्
developer_tools common hi अनुवाद् कर्ने का औजार
diary developer_tools hi डिनचर्या पट्रिका
done developer_tools hi हो गया

View File

@ -1,73 +0,0 @@
add developer_tools hr dodaj
add change developer_tools hr Dodaj promjenu
add more developer_tools hr Dodaj još
add new phrase developer_tools hr Dodaj novu frazu
add phrase developer_tools hr dodaj frazu
allows you to add a single phrase developer_tools hr Omogućuje dodavanje jedne fraze
application developer_tools hr Aplikacija
back developer_tools hr Povratak
cancel developer_tools hr Otkaži
change developer_tools hr Promijeni
changelog entry has been added developer_tools hr Dodana je promjena zapisa
changelogs developer_tools hr promjena zapisa
clears the internal buffer, all changes made sofar are lost developer_tools hr očistu unutarnji međuspremnik, sve dosadašnje promjene će biti izgubljene
create new language file developer_tools hr Napravi novu jezičnu datoteku
create sgml file developer_tools hr Napravi SGML datoteku
developer tools - preferences developer_tools hr Razvojni alati - postavke
developer_tools common hr Prevoditeljski alati
diary developer_tools hr Dnevnik
done developer_tools hr gotov
download developer_tools hr Prenesi sa poslužitelja
download the lang-file to be saved in the apps setup-dir developer_tools hr Prenesi sa poslužitelja jezičnu datoteku radi spremanja u aplikacijsku mapu postavki
edit developer_tools hr Uredi
installed applications developer_tools hr instalirane aplikacije
language file management developer_tools hr Uređivanje jezične datoteke
list changelogs developer_tools hr Prikaži promjene zapisa
load developer_tools hr Unesi
loading source langfile developer_tools hr Unosim izvornu jezičnu datoteku
loading target langfile developer_tools hr Unosim ciljanu jezičnu datoteku
loads the selected lang-files, to be modified in the next steps developer_tools hr Loads the selected lang-files, to be modified in the next steps
message developer_tools hr Poruka
message_id in english developer_tools hr Indetitet poruke na engleskom jeziku
no file developer_tools hr nema datoteke
ok developer_tools hr uredu
original developer_tools hr Original
phrase in english (or empty if identical) developer_tools hr Fraza na engleskom (ili prazno ako je indentično)
preferences developer_tools hr Postavke
preferences have been updated developer_tools hr Preferences have been updated
project developer_tools hr Projekt
remove developer_tools hr Makni
returns to the application list, not saved changes get lost !!! developer_tools hr Vraća se aplikaciji, nespremljene promjene će biti izgubljene !!!
revert developer_tools hr Okreni
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools hr Sprema dodane/promijenjene prijevode u međuspremnik, radi upotrebe u daljnim koracima
search changelogs developer_tools hr Traži promjene zapisa
search for missing phrase developer_tools hr Traži nedostajuću frazu
search new phrases developer_tools hr Traži novu frazu
searches the source-code for phrases not in the actual source-lang-file developer_tools hr Pretražuje izvorni kod za fraze koje nisu u trenutnoj jezičnoj datoteci
select project developer_tools hr Izaberite projekt
sf project tracker developer_tools hr SF pratilac projekata
sf project tracker preferences preferences hr Postavke SF pratilaca projekata
source language developer_tools hr Izvorni jezik
sourceforge project id developer_tools hr Sourceforge project ID
sourceforge project tracker developer_tools hr Sourceforge project tracker
sourceforge project tracker preferences developer_tools hr Sourceforge project tracker preferences
step developer_tools hr Korak
submit developer_tools hr Predaj
target language developer_tools hr Ciljani jezik
title developer_tools hr Naslov
translate developer_tools hr Pravedi
translation developer_tools hr Prijevod
translation of phrase developer_tools hr Prijevod fraze
update developer_tools hr Obnovi
update database developer_tools hr Obnovi bazu podataka
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools hr Updates the translations of both lang-files in your database, so you can verify your work immediately
version developer_tools hr Verzija
write developer_tools hr Zapiši
write the lang-file to the apps setup-dir developer_tools hr Zapisuje jezičnu datoteku u aplikacijsku mapu postavki
write to lang table developer_tools hr Zapiši u jeziočnu tabelu
writing langfile for '%1' ... developer_tools hr Zapiši jezičnu datoteku za '%1' ...
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools hr Morate [Spremiti] svaku promjenu u gornjim poljima, prije nego što prijeđete na slijedeći korak !!!
you must a version developer_tools hr Morate verziju
you must enter a change developer_tools hr Morate unijeti promjenu
you must select a project developer_tools hr Morate izabrati projekt
you need to set your preferences for this app developer_tools hr Morate postaviti postavke za ovu aplikaciju

View File

@ -1,74 +0,0 @@
add developer_tools hu Hozzáad
add change developer_tools hu Módosítás hozzáadása
add more developer_tools hu Kiegészítés hozzáadása
add new phrase developer_tools hu Új bejegyzés hozzáadása
add phrase developer_tools hu Bejegyzés hozzáadása
allows you to add a single phrase developer_tools hu Egyszerű bejegyzés hozzáadása megengedett
application developer_tools hu Alkalmazás
back developer_tools hu Vissza
cancel developer_tools hu Mégsem
change developer_tools hu Változtat
changelog entry has been added developer_tools hu A módosítás a naplóban bejegyzeve
changelogs developer_tools hu Módosítási naplóbejgyezések
clears the internal buffer, all changes made sofar are lost developer_tools hu A belső tár törlése, az eddig módosítások elvesznek
create new language file developer_tools hu Új nyelvi file létrehozása
create sgml file developer_tools hu SGML file létrehozésa
developer tools - preferences developer_tools hu Nyelvi eszközök - tulajdonságok
developer_tools common hu Nyelvi eszközök
diary developer_tools hu Napló
done developer_tools hu Kész
download developer_tools hu Letöltés
download the lang-file to be saved in the apps setup-dir developer_tools hu A nyelvi file letöltése az alkalmazások mappa setup almappájába
edit developer_tools hu Szerkesztés
installed applications developer_tools hu Telepített alkalmazások
language file management developer_tools hu Nyelvi fileok kezelése
list changelogs developer_tools hu Naplóbejegyzések listája
load developer_tools hu Betöltés
loading source langfile developer_tools hu Forrás nyelvi file betöltése
loading target langfile developer_tools hu Cél nyelvi file betöltése
loads the selected lang-files, to be modified in the next steps developer_tools hu A kiválasztott nyelvi file betöltése módosítás céljából
message developer_tools hu Üzenet
message_id in english developer_tools hu Üzenet azaonosító angolul
no file developer_tools hu nincs file
ok developer_tools hu OK
original developer_tools hu Eredeti
phrase in english (or empty if identical) developer_tools hu Kifejezés angolul (megegyezik ha üres)
preferences developer_tools hu Tulajdonságok
preferences have been updated developer_tools hu A tulajdonságok frissítve lettek
project developer_tools hu Projekt
remove developer_tools hu Eltávolít
removed %1 phrases from the target language, as they are not present in the source language! developer_tools hu %1 kifejezés nem szerepel a forrás nyelvi fileban ezért eltávolítva a cél nyelvi fileból is!
returns to the application list, not saved changes get lost !!! developer_tools hu Visszatérés az alkalmazáslistához, nem mentett módosítások elvesznek!
revert developer_tools hu Visszaállít
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools hu Az újonnan létrehozott és módosított fordítások mentése egy belső tárba későbbi felhasználás céljából.
search changelogs developer_tools hu Naplóbejegyzések keresése
search for missing phrase developer_tools hu Hiányzó kifejezések keresése
search new phrases developer_tools hu Új kifejezések keresése
searches the source-code for phrases not in the actual source-lang-file developer_tools hu Keresés a forráskódban kifejezésekre, nem az aktuális forrás nyelvi fileban
select project developer_tools hu Projekt kiválasztása
sf project tracker developer_tools hu SF Projekt követő
sf project tracker preferences preferences hu SF Projekt követő tulajdonságok
source language developer_tools hu Forrás nyelv
sourceforge project id developer_tools hu Sourceforge projekt azonosító
sourceforge project tracker developer_tools hu Sourceforge projekt követő
sourceforge project tracker preferences developer_tools hu Sourceforge projekt azonosító tulajdonságok
step developer_tools hu Lépés
submit developer_tools hu Elküld
target language developer_tools hu Cél nyelv
title developer_tools hu Cím
translate developer_tools hu Fordít
translation developer_tools hu Fordítás
translation of phrase developer_tools hu Kifejezés fordítása
update developer_tools hu Frissít
update database developer_tools hu Adatbázis frissítés
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools hu A lefordított kifejezések adatbázisba írása, hogy azonnal ellenőrizhesd munkádat
version developer_tools hu Verzió
write developer_tools hu Írás
write the lang-file to the apps setup-dir developer_tools hu A nyelvi file mentése az alkalmazés setup mappájába
write to lang table developer_tools hu Mentés a nyelvi táblába
writing langfile for '%1' ... developer_tools hu %' mentése a nyelvi fileba
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools hu A következő lépéshez először mentened kell minden módosítás a fenti mezőkben!
you must a version developer_tools hu Ki kell választanod a verziót
you must enter a change developer_tools hu Meg kell adnod a változást
you must select a project developer_tools hu Ki kell választanod a projektet
you need to set your preferences for this app developer_tools hu Be kell állítanod a tulajdonságokat ehhez az alkalmazáshoz

View File

@ -1,64 +0,0 @@
add developer_tools id Tambah
add change developer_tools id Tambah perubahan
add more developer_tools id Tambah lagi
add new phrase developer_tools id Tambah frasa baru
add phrase developer_tools id tambah frasa
allows you to add a single phrase developer_tools id Mengijinkan anda menambah frasa tunggal
application developer_tools id Aplikasi
back developer_tools id Kembali
cancel developer_tools id Batal
change developer_tools id Perubahan
changelog entry has been added developer_tools id Entri log pengubahan telah ditambahkan
changelogs developer_tools id Log pengubahan
clears the internal buffer, all changes made sofar are lost developer_tools id Bersihkan buffer internal, semua pengubahan selama ini akan hilang
create new language file developer_tools id Bikin Berkas Bahasa Baru
create sgml file developer_tools id Bikin berkas SGML
developer tools - preferences developer_tools id Kesukaan - Alat-alat Pengembang
developer_tools common id Penerjemahan
diary developer_tools id Diari
done developer_tools id selesai
download developer_tools id Unduh
download the lang-file to be saved in the apps setup-dir developer_tools id Unduh berkas bahasa untuk disimpan ke direktori setup aplikasi
edit developer_tools id Edit
installed applications developer_tools id Aplikasi terpasang
language file management developer_tools id Manajemen berkas bahasa
list changelogs developer_tools id Daftar log pengubahan
load developer_tools id Muatkan
loading source langfile developer_tools id Memuat berkas bahasa sumber
loading target langfile developer_tools id Memuat berkas bahasa tujuan
loads the selected lang-files, to be modified in the next steps developer_tools id Memuat berkas bahasa terpilih untuk diubah pada langkah berikutnya
message developer_tools id Pesan
message_id in english developer_tools id message_id dalam bahasa Inggris
no file developer_tools id tiada berkas
ok developer_tools id ok
original developer_tools id Asal-Muasal
phrase in english (or empty if identical) developer_tools id Frasa dalam bahasa Inggris (atau kosongkan bila sama)
preferences developer_tools id Kesukaan
preferences have been updated developer_tools id Kesukaan telah diperbarui
project developer_tools id Proyek
remove developer_tools id Buang
removed %1 phrases from the target language, as they are not present in the source language! developer_tools id %1 frasa dibuang dari bahasa sasaran, karena tidak tersedia dalam bahasa sumber!
returns to the application list, not saved changes get lost !!! developer_tools id Kembali ke daftar aplikasi, pengubahan yang tidak disimpan akan hilang !!!
revert developer_tools id Kembalikan
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools id Simpan penambahan/pengubahan penerjemahan ke dalam buffer internal, untuk digunakan pada langkah berikutnya
search changelogs developer_tools id Cari di log-perubahan
search for missing phrase developer_tools id Cari frasa yang hilang
search new phrases developer_tools id Cari frasa baru
searches the source-code for phrases not in the actual source-lang-file developer_tools id Cari frasa dalam kode-sumber yang tidak terdapat dalam berkas bahasa-sumber
select project developer_tools id Pilih proyek
source language developer_tools id Bahasa Sumber
step developer_tools id Langkah
submit developer_tools id Kirim
target language developer_tools id Bahasa Tujuan
title developer_tools id Judul
translate developer_tools id Terjemahkan
translation developer_tools id Terjemahan
translation of phrase developer_tools id Frasa terjemahan
update developer_tools id Perbarui
update database developer_tools id Perbarui Database
version developer_tools id Versi
write developer_tools id Tulis
write the lang-file to the apps setup-dir developer_tools id Tulis berkas bahasa ke direktori setup aplikasi
write to lang table developer_tools id Tulis ke tabel bahasa
writing langfile for '%1' ... developer_tools id Menuliskan berkas bahasa '%1' ...
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools id Anda harus [Simpan] setiap melakukan pengubahan baris diatas, sebelum melanjutkan langkah berikutnya !!!

View File

@ -1,74 +0,0 @@
add developer_tools it aggiungi
add change developer_tools it Aggiungi modifica
add more developer_tools it Aggiungi altro
add new phrase developer_tools it Aggiungi una nuova frase
add phrase developer_tools it Aggiungi frase
allows you to add a single phrase developer_tools it Consente di inserire una singola frase
application developer_tools it Applicazione
back developer_tools it Indietro
cancel developer_tools it Annulla
change developer_tools it Cambia
changelog entry has been added developer_tools it Voce aggiunta al log delle modifiche
changelogs developer_tools it Changelog
clears the internal buffer, all changes made sofar are lost developer_tools it Pulisce il buffer interno, tutti i cambiamenti saranno persi
create new language file developer_tools it Crea nuovo File Linguaggio
create sgml file developer_tools it Crea file SGML
developer tools - preferences developer_tools it Strumenti Sviluppatori - preferenze
developer_tools common it Strumenti di Traduzione
diary developer_tools it Diario
done developer_tools it fatto
download developer_tools it Download
download the lang-file to be saved in the apps setup-dir developer_tools it Scarica il file .lang da salvare nella directory setup dell'applicazione
edit developer_tools it Modifica
installed applications developer_tools it Applicazioni Installate
language file management developer_tools it Gestione dei File di Linguaggio
list changelogs developer_tools it Elenco log delle modifiche
load developer_tools it Carica
loading source langfile developer_tools it Caricamento file linguaggio sorgente
loading target langfile developer_tools it Caricamento file linguaggio destinazione
loads the selected lang-files, to be modified in the next steps developer_tools it Carica i file linguaggio selezionati, per l'utilizzo nella fase successiva
message developer_tools it Messaggio
message_id in english developer_tools it Message_id in Inglese
no file developer_tools it Nessun File
ok developer_tools it ok
original developer_tools it Originale
phrase in english (or empty if identical) developer_tools it Frase in INGLESE (o vuota se identica)
preferences developer_tools it Preferenze
preferences have been updated developer_tools it Le Preferenze sono state aggiornate
project developer_tools it Progetto
remove developer_tools it Rimuovi
removed %1 phrases from the target language, as they are not present in the source language! developer_tools it Rimosse %1 frase/i dal linguaggio destinazione, dato che non è/sono presenti nel linguaggio origine!
returns to the application list, not saved changes get lost !!! developer_tools it Ritorna alla lista delle applicazioni, tutti i cambiamenti non salvati saranno perduti !!!
revert developer_tools it Ripristina
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools it Salva le traduzioni aggiunte/modificate in un buffer interno, per essere usate nei passaggi successivi
search changelogs developer_tools it Cerca nel Log delle Modifiche
search for missing phrase developer_tools it Cerca frase mancante
search new phrases developer_tools it Cerca nuove frasi
searches the source-code for phrases not in the actual source-lang-file developer_tools it Cerca nel codice sorgente frasi non presenti nel file .lang sorgente
select project developer_tools it Seleziona progetto
sf project tracker developer_tools it Monitoraggio del progetto su SF
sf project tracker preferences preferences it preferenze per il monitoraggio del progetto du SF
source language developer_tools it Linguaggio di Origine
sourceforge project id developer_tools it ID del progetto su SourceForge
sourceforge project tracker developer_tools it Monitoraggio progetto su SourceForge
sourceforge project tracker preferences developer_tools it Preferenze monitoraggio progetto su SourceForge
step developer_tools it Fase
submit developer_tools it Invia
target language developer_tools it Linguaggio di Destinazione
title developer_tools it Titolo
translate developer_tools it Traduci
translation developer_tools it Traduzione
translation of phrase developer_tools it Traduzione della frase
update developer_tools it Aggiorna
update database developer_tools it Aggiorna database
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools it Aggiorna le traduzioni di tutti e due i file .lang nel database, così è possibile verificare immediatamente il lavoro
version developer_tools it Versione
write developer_tools it Scrivi
write the lang-file to the apps setup-dir developer_tools it Scrive il file .lang nella directory setup dell'applicazione
write to lang table developer_tools it Scrivi nella Tabella Linguaggio
writing langfile for '%1' ... developer_tools it Scrittura in corso del file linguaggio per '%1' ...
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools it Devi cliccare [Salva] per ogni modifica apportata nei campi soprastanti, prima di poter proseguire alla fase successiva !!!
you must a version developer_tools it Inserire una versione
you must enter a change developer_tools it Inserire una modifica
you must select a project developer_tools it Selezionare un progetto
you need to set your preferences for this app developer_tools it Devono essere impostate le preferenze per questa applicazione

View File

@ -1,73 +0,0 @@
add developer_tools iw הוסף
add change developer_tools iw הוסף שינוי
add more developer_tools iw הוסף עוד
add new phrase developer_tools iw הוסף פראזה חדשה
add phrase developer_tools iw הוסף פראזה
allows you to add a single phrase developer_tools iw מאפשר לך להוסיף פראזה יחידה
application developer_tools iw יישום
back developer_tools iw חזור
cancel developer_tools iw בטל
change developer_tools iw שנה
changelog entry has been added developer_tools iw הוספה רשומה ליומן השינוים
changelogs developer_tools iw יומני שינוי
clears the internal buffer, all changes made sofar are lost developer_tools iw מנקה את החוצץ הפנימי, כל השינוים שבוצעו עד עתה נאבדים
create new language file developer_tools iw צור קובץ שפה חדש
create sgml file developer_tools iw SGML צור קובץ
developer tools - preferences developer_tools iw עדיפויות - כלי מפתח
developer_tools common iw כלי תרגום
diary developer_tools iw יומן
done developer_tools iw בוצע
download developer_tools iw הורד
download the lang-file to be saved in the apps setup-dir developer_tools iw של היישום setup-הורד את קובץ השפה שתשמר במחיצת ה
edit developer_tools iw ערוך
installed applications developer_tools iw יישומים מעודכנים
language file management developer_tools iw ניהול קבצי שפה
list changelogs developer_tools iw רשום יומני שינוי
load developer_tools iw טען
loading source langfile developer_tools iw טוען קובץ שפת מקור
loading target langfile developer_tools iw טוען קובץ שפת יעד
loads the selected lang-files, to be modified in the next steps developer_tools iw טוען את קבצי השפה הנבחרים, הם ישונו בשלבים הבאים
message developer_tools iw הודעה
message_id in english developer_tools iw זיהוי הודעה באנגלית
no file developer_tools iw אין קובץ
ok developer_tools iw בסדר
original developer_tools iw מקור
phrase in english (or empty if identical) developer_tools iw (פרזה באנגלית (או ריק אם זהה
preferences developer_tools iw עדיפויות
preferences have been updated developer_tools iw עדיפויות עודכנו
project developer_tools iw !פרויקט
remove developer_tools iw הסר
returns to the application list, not saved changes get lost !!! developer_tools iw !חוזר אל רשימת היישומים, שינוים שלא נשמרו הולכים לאיבוד
revert developer_tools iw שחזר
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools iw שומר את התרגומים החדשים/השונים לחוצץ פנימי, ישרת אותנו בצעדי ההמשך
search changelogs developer_tools iw חפש ביומני השינוי
search for missing phrase developer_tools iw חפש פראזה חסרה
search new phrases developer_tools iw חפש פראזות חדשות
searches the source-code for phrases not in the actual source-lang-file developer_tools iw מחפש בקוד-מקור פרזות שלא נמצאות בקובץ שפת המקור
select project developer_tools iw בחר פרויקט
sf project tracker developer_tools iw SF איתור פרויקטים של
sf project tracker preferences preferences iw SF עדיפויות של איתור פרויקטים של
source language developer_tools iw שפת מקור
sourceforge project id developer_tools iw SourceForge זיהוי פרויקט של
sourceforge project tracker developer_tools iw SourceForge איתור פרויקטים של
sourceforge project tracker preferences developer_tools iw SourceForge עדיפויות של איתור פרויקטים של
step developer_tools iw צעד
submit developer_tools iw הגש
target language developer_tools iw שפת יעד
title developer_tools iw כותרת
translate developer_tools iw תרגם
translation developer_tools iw תרגום
translation of phrase developer_tools iw תרגום פראזה
update developer_tools iw עדכן
update database developer_tools iw עדכן בסיס נתונים
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools iw מעדכן את התרגום של שני קבצי השפה בבסיס הנתונים שלך, כדי לאמת את עבודתך מידית
version developer_tools iw גירסא
write developer_tools iw כתוב
write the lang-file to the apps setup-dir developer_tools iw כתוב את קובץ השפה למחיצת setup של היישום
write to lang table developer_tools iw כתוב לטבלת השפה
writing langfile for '%1' ... developer_tools iw כתוב קובץ שפה עבור '%1'...
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools iw !עליך ל[שמור] כל שינוי ידני שבצעת בשדות לעיל, לפנ שתתקדם לשלבים הבאים
you must a version developer_tools iw חובה לציין גירסא
you must enter a change developer_tools iw עליך לציין שינוי
you must select a project developer_tools iw עליך לבחור פרויקט
you need to set your preferences for this app developer_tools iw עליך לקבוע את העדיפויות ליישום זה

View File

@ -1,72 +0,0 @@
add developer_tools ja 追加
add change developer_tools ja 履歴追加
add more developer_tools ja さらに追加
add new phrase developer_tools ja 文言追加
add phrase developer_tools ja 文言追加
allows you to add a single phrase developer_tools ja 文言をひとつ追加します
application developer_tools ja アプリケーション
back developer_tools ja 戻る
cancel developer_tools ja キャンセル
change developer_tools ja 変更内容
changelog entry has been added developer_tools ja 変更履歴が追加されました
changelogs developer_tools ja 変更履歴
clears the internal buffer, all changes made sofar are lost developer_tools ja 内部バッファをクリアします(全ての変更は破棄されます)
create new language file developer_tools ja 新しい言語ファイルを作成する
create sgml file developer_tools ja SGMLファイル作成
developer tools - preferences developer_tools ja Developer tools - ユーザ設定
developer_tools common ja 翻訳ツール
diary developer_tools ja 日誌
done developer_tools ja done
download developer_tools ja ダウンロード
download the lang-file to be saved in the apps setup-dir developer_tools ja アプリケーションのsetupディレクトリに保存するためにダウンロードする
edit developer_tools ja 編集
installed applications developer_tools ja インストールされているアプリケーション
language file management developer_tools ja 言語ファイル管理
list changelogs developer_tools ja 履歴一覧
load developer_tools ja 読み込み
loading source langfile developer_tools ja 元の言語ファイル読み込み
loading target langfile developer_tools ja 対象言語ファイル読み込み
loads the selected lang-files, to be modified in the next steps developer_tools ja 次のステップで修正するために選択されたlang-fileを読み込む
message developer_tools ja メッセージ
message_id in english developer_tools ja メッセージID(英語)
no file developer_tools ja ファイルなし
ok developer_tools ja OK
original developer_tools ja オリジナル
phrase in english (or empty if identical) developer_tools ja 英語の文言(同一なら空)
preferences developer_tools ja ユーザ設定
preferences have been updated developer_tools ja ユーザ設定が更新されました
project developer_tools ja プロジェクト
remove developer_tools ja 削除
returns to the application list, not saved changes get lost !!! developer_tools ja アプリケーションの一覧に戻ります。保存されていない変更点は破棄されます!!!
revert developer_tools ja やり直し
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools ja 以降のステップで使うために追加/変更した翻訳文を内部バッファに保存します
search changelogs developer_tools ja 履歴検索
search for missing phrase developer_tools ja 欠落文言検索
search new phrases developer_tools ja 新しい文言を検索
searches the source-code for phrases not in the actual source-lang-file developer_tools ja source-lang-fileに無い文言をソースコードから検索
select project developer_tools ja プロジェクト選択
sf project tracker developer_tools ja SF Project tracker
sf project tracker preferences preferences ja SF Project tracker ユーザ設定
source language developer_tools ja 元の言語
sourceforge project id developer_tools ja Sourceforge project ID
sourceforge project tracker developer_tools ja Sourceforge project tracker
sourceforge project tracker preferences developer_tools ja Sourceforge project tracker ユーザ設定
step developer_tools ja ステップ
submit developer_tools ja Submit
target language developer_tools ja 対象言語
title developer_tools ja Title
translate developer_tools ja Translate
translation developer_tools ja 翻訳
translation of phrase developer_tools ja 翻訳文言
update developer_tools ja 訂正
update database developer_tools ja データベースの更新
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools ja データベースの両方のlang-fileの翻訳を更新します。結果をすぐに確認できます。
version developer_tools ja バージョン
write developer_tools ja Write
write the lang-file to the apps setup-dir developer_tools ja アプリケーションのsetupディレクトリにlang-fileを保存する
write to lang table developer_tools ja 書き込み
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools ja 上の項目を変更したら、次のステップに進む前に毎回[保存]する必要があります!!!
you must a version developer_tools ja バージョンを入力して下さい
you must enter a change developer_tools ja 変更内容を入力して下さい
you must select a project developer_tools ja プロジェクトを選択して下さい
you need to set your preferences for this app developer_tools ja このアプリケーションのユーザ設定を行う必要があります

View File

@ -1,73 +0,0 @@
add developer_tools ko 추가
add change developer_tools ko 변경 추가
add more developer_tools ko 더 추가
add new phrase developer_tools ko 새 구문 추가
add phrase developer_tools ko 구문 추가
allows you to add a single phrase developer_tools ko 단일 구문 추가 허용
application developer_tools ko 응용프로그램
back developer_tools ko 뒤로
cancel developer_tools ko 취소
change developer_tools ko 변경
changelog entry has been added developer_tools ko Changelog 항목이 추가되었습니다
changelogs developer_tools ko Changlogs
clears the internal buffer, all changes made sofar are lost developer_tools ko 내부 버퍼를 지우고, 이제까지 변경한 것은 모두 잃게됩니다
create new language file developer_tools ko 새 언어파일 생성
create sgml file developer_tools ko SGML 파일 생성
developer tools - preferences developer_tools ko 개발 도구 - 환경설정
developer_tools common ko 번역 도구
diary developer_tools ko 일기
done developer_tools ko 완료
download developer_tools ko 내려받기
download the lang-file to be saved in the apps setup-dir developer_tools ko 내려받은 언어-파일은 응용프로그램 설정-디렉토리에 저장됩니다
edit developer_tools ko 편집
installed applications developer_tools ko 설치된 응용프로그램
language file management developer_tools ko 언어파일 관리
list changelogs developer_tools ko changelogs 목록
load developer_tools ko 불러오기
loading source langfile developer_tools ko 원본 언어파일 불러오는중
loading target langfile developer_tools ko 대상 언어파일 불러오는중
loads the selected lang-files, to be modified in the next steps developer_tools ko 다음 단계에서 변경하기 위해, 선택된 언어파일들을 불러옵니다
message developer_tools ko 메세지
message_id in english developer_tools ko 영어 message_id
no file developer_tools ko 파일 없음
ok developer_tools ko 확인
original developer_tools ko 원본
phrase in english (or empty if identical) developer_tools ko 영어로 된 구문(이나 뜻이 명확하다면 비워도됨)
preferences developer_tools ko 환경설정
preferences have been updated developer_tools ko 환경설정이 갱신되었습니다
project developer_tools ko 프로젝트
remove developer_tools ko 삭제
returns to the application list, not saved changes get lost !!! developer_tools ko 응용프로그램 목록으로 돌아갑니다, 단 저장되지 않은 변경사항은 모두 잃게됩니다!!
revert developer_tools ko 반전(Revert)
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools ko 추가/변경된 번역내용을 내부버퍼로 저장, 이는 다음 단계에서 사용하게 됩니다
search changelogs developer_tools ko changelogs 검색
search for missing phrase developer_tools ko 없는 구문 검색
search new phrases developer_tools ko 새로운 구문 검색
searches the source-code for phrases not in the actual source-lang-file developer_tools ko 소스-언어-파일에 실제나타나지 않은 구문을 소스코드에서 탐색
select project developer_tools ko 프로젝트를 선택
sf project tracker developer_tools ko SF 프로젝트 추적기
sf project tracker preferences preferences ko SF 프로젝트 추적기 환경설정
source language developer_tools ko 소스 언어
sourceforge project id developer_tools ko 소스포지 프로젝트 ID
sourceforge project tracker developer_tools ko 소스포지 프로젝트 추적기
sourceforge project tracker preferences developer_tools ko 소스포지 프로젝트 추적기 환경설정
step developer_tools ko 단계
submit developer_tools ko 보냄(Submit)
target language developer_tools ko 타겟 언어
title developer_tools ko 제목
translate developer_tools ko 번역하기
translation developer_tools ko 번역
translation of phrase developer_tools ko 구문 번역
update developer_tools ko 갱신
update database developer_tools ko 데이터베이스 갱신
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools ko 두개의 언어파일 번역을 데이터베이스에 갱신하고, 작업내역을 즉시 확인할수 있습니다
version developer_tools ko 버전
write developer_tools ko 쓰기
write the lang-file to the apps setup-dir developer_tools ko 어플리케이션 설정디렉토리에 언어-파일 쓰기
write to lang table developer_tools ko 언어 테이블 쓰기
writing langfile for '%1' ... developer_tools ko '%1' , 언어파일을 쓰고 있습니다.
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools ko 직접 수정하신 모든 것은 반드시 [저장] 하셔야 하며, 다음단계로 진행하기 전에 꼭 해주세요!!
you must a version developer_tools ko ** 버전을 반드시 입력
you must enter a change developer_tools ko ** 변경점을 반드시 입력하세요
you must select a project developer_tools ko 프로젝트를 반드시 선택하셔야 합니다.
you need to set your preferences for this app developer_tools ko 이 응용프로그램의 환경설정을 반드시 하셔야합니다.

View File

@ -1,3 +0,0 @@
download developer_tools lo ດາວໂຫຼດ
installed applications developer_tools lo ຕິດຕັ້ງ ແອັບພຼິເຄຊັນສ
remove developer_tools lo ລຶບອອກ

View File

@ -1,65 +0,0 @@
add developer_tools lv pievienot
add change developer_tools lv Pievienot izmaiņas
add more developer_tools lv Pievienot vēl
add new phrase developer_tools lv Pievienot jaunu frāzi
add phrase developer_tools lv pievienot frāzi
allows you to add a single phrase developer_tools lv Atļauj Jums pievienot vienu frāzi
application developer_tools lv Programma/Modulis
back developer_tools lv Atpakaļ
cancel developer_tools lv Atcelt
change developer_tools lv Mainīt
changelog entry has been added developer_tools lv Izmaiņu sarakstā jauns ieraksts
changelogs developer_tools lv Izmaiņu logs
clears the internal buffer, all changes made sofar are lost developer_tools lv Iztīra iekšējo datu buferi, visas izmaiņas, kas veiktas līdz šim, tiks zaudētas
create new language file developer_tools lv Izveidot jaunu valodas failu
create sgml file developer_tools lv Izveidot SGML failu
developer tools - preferences developer_tools lv Sistēmas veidotāja rīki - vēlamie iestatījumi
developer_tools common lv Tulkošanas rīki
diary developer_tools lv Dienasgrāmata
done developer_tools lv darīts
download developer_tools lv Lejupielādēt
download the lang-file to be saved in the apps setup-dir developer_tools lv Lejupielādēt valodas failu, lai saglabātu programmu izvietnes direktorijā
edit developer_tools lv Labot
installed applications developer_tools lv Izvietotās programmas/moduļi
language file management developer_tools lv valodas failu administrēšana
list changelogs developer_tools lv Uzskaitīt izmaiņu sarakstus
load developer_tools lv Ielādēt
loading source langfile developer_tools lv Notiek apstrādājamā valodas faila ielāde
loading target langfile developer_tools lv Notiek noglabājamā valodas faila ielāde
loads the selected lang-files, to be modified in the next steps developer_tools lv Ielādē iezīmētos valodas failus, lai veiktu tajos izmaiņas turpmākajos darbības posmos
message developer_tools lv Ziņa
message_id in english developer_tools lv ziņas ID angliski
no file developer_tools lv nav faila
ok developer_tools lv ok
original developer_tools lv Oriģināls
phrase in english (or empty if identical) developer_tools lv Frāze angliski (vai jāatstāj tukšs, ja identisks)
preferences developer_tools lv Vēlamie iestatījumi
preferences have been updated developer_tools lv Vēlamie iestatījumi tika atjaunoti
project developer_tools lv Projekts
remove developer_tools lv Izdzēst
returns to the application list, not saved changes get lost !!! developer_tools lv Atgriesties pie programmatūras/moduļu saraksta, nesaglabātās izmaiņas tiks zaudētas!!!
revert developer_tools lv Atgriezt atpakaļ
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools lv Saglabā pievienotos/izmainītos tulkojumus iekšējā buferī, lai izmantotu nākamajos soļos
search for missing phrase developer_tools lv Meklēt trūkstošo frāzi
search new phrases developer_tools lv Meklēt jaunas frāzes
select project developer_tools lv Atzīmēt projektu
sf project tracker developer_tools lv SF projektu meklētājs
sf project tracker preferences preferences lv SF projektu meklētāja iestatījumi
source language developer_tools lv Pamatvaloda
step developer_tools lv Solis
submit developer_tools lv Iesniegt
target language developer_tools lv Mērķa valoda
title developer_tools lv Virsraksts
translate developer_tools lv Tulkot
translation developer_tools lv Tulkojums
translation of phrase developer_tools lv Frāzes tulkojums
update developer_tools lv Atjaunināt
update database developer_tools lv Atjaunināt datubāzi
version developer_tools lv Versija
write developer_tools lv Rakstīt
write to lang table developer_tools lv Rakstīt lang tabulā
writing langfile for '%1' ... developer_tools lv Raksta langfailu "%1"...
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools lv Pirms pārej pie nākamā soļa, tev jāsaglabā veiktās izmaiņas!!!
you must enter a change developer_tools lv Tev jāievada izmaiņas
you must select a project developer_tools lv Tev jāatzīmē projekts
you need to set your preferences for this app developer_tools lv Tev jāuzstāda savi iestatījumi šai aplikācijai

View File

@ -1,74 +0,0 @@
add developer_tools nl toevoegen
add change developer_tools nl Verandering toevoegen
add more developer_tools nl Meer toevoegen
add new phrase developer_tools nl Nieuwe zin toevoegen
add phrase developer_tools nl Nieuwe frasen
allows you to add a single phrase developer_tools nl Staat u toe een enkele frase toe te voegen
application developer_tools nl Toepassing
back developer_tools nl Terug
cancel developer_tools nl Annuleren
change developer_tools nl Veranderen
changelog entry has been added developer_tools nl Changelog entry is toegevoegd
changelogs developer_tools nl Changelogs
clears the internal buffer, all changes made sofar are lost developer_tools nl Maakt de interne buffer leeg, alle verandering tot nu gaan verloren.
create new language file developer_tools nl Maak nieuw taalbestand
create sgml file developer_tools nl Maak SGML-bestand
developer tools - preferences developer_tools nl Ontwikkelaarshulpmiddelen - voorkeuren
developer_tools common nl Vertaalhulpmiddelen
diary developer_tools nl Dagboek
done developer_tools nl klaar
download developer_tools nl Downloaden
download the lang-file to be saved in the apps setup-dir developer_tools nl Download het taalbestand om het op te slaan in de setupdirectorie van de toepassing.
edit developer_tools nl Wijzigen
installed applications developer_tools nl Geïnstalleerde toepassingen
language file management developer_tools nl Taalbestandenbeheer
list changelogs developer_tools nl Toon changelogs
load developer_tools nl Openen
loading source langfile developer_tools nl Brontaalbestand openen
loading target langfile developer_tools nl Doeltaalbestand openen
loads the selected lang-files, to be modified in the next steps developer_tools nl Opent de geselecteerde taalbestanden, om gewijzigd to worden in de volgende stappen
message developer_tools nl Bericht
message_id in english developer_tools nl bericht ID in het Engels
no file developer_tools nl geen bestand
ok developer_tools nl Ok
original developer_tools nl Origineel
phrase in english (or empty if identical) developer_tools nl Zin in het Engels (of leeg indien gelijk)
preferences developer_tools nl Voorkeuren
preferences have been updated developer_tools nl Voorkeuren zijn bijgewerkt
project developer_tools nl Project
remove developer_tools nl Verwijderen
removed %1 phrases from the target language, as they are not present in the source language! developer_tools nl %1 teksten uit de doeltaal verwijderd omdat ze niet (meer) voorkomen in de brontaal!
returns to the application list, not saved changes get lost !!! developer_tools nl Ga terug naar de lijst met toepassingen. Niet opgeslagen verandering gaan verloren !!!
revert developer_tools nl Draai terug
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools nl Slaat de toegevoegde en gewijzigde vertalingen op in een intern geheugen om gebruikt te worden in de volgende stappen
search changelogs developer_tools nl Doorzoek changelogs
search for missing phrase developer_tools nl Zoek naar missende zinnen
search new phrases developer_tools nl Zoek naar nieuwe zinnen
searches the source-code for phrases not in the actual source-lang-file developer_tools nl Doorzoekt de broncode naar phrasen die niet voorkomen in de huidige taalbestanden
select project developer_tools nl Selecteer project
sf project tracker developer_tools nl SF Project tracker
sf project tracker preferences preferences nl SF Project tracker voorkeuren
source language developer_tools nl Brontaal
sourceforge project id developer_tools nl SourceForge project ID
sourceforge project tracker developer_tools nl SourceForge project tracker
sourceforge project tracker preferences developer_tools nl SourceForge project tracker voorkeuren
step developer_tools nl Stap
submit developer_tools nl Verzenden
target language developer_tools nl Doeltaal
title developer_tools nl Titel
translate developer_tools nl Vertaal
translation developer_tools nl Vertaling
translation of phrase developer_tools nl Vertaling van de zin
update developer_tools nl Bijwerken
update database developer_tools nl Database bijwerken
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools nl Werkt de vertalingen van beide taalbestanden bij in de database zodat u uw werk direct kunt controleren
version developer_tools nl Versie
write developer_tools nl Naar bestand schrijven
write the lang-file to the apps setup-dir developer_tools nl Schrijf het taalbestand naar de setupdirectory van de toepassing
write to lang table developer_tools nl Schrijf naar de taaltabel in de database
writing langfile for '%1' ... developer_tools nl Taalbestand voor '%1' wordt geschreven...
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools nl !!! U moet na elke handeling hierboven op [Opslaan] klikken, voordat u verder kunt met de volgende stap !!!
you must a version developer_tools nl U moet een versie invoeren
you must enter a change developer_tools nl U moet een verandering toevoegen
you must select a project developer_tools nl U moet een project selecteren
you need to set your preferences for this app developer_tools nl U moet de voorkeuren voor deze toepassingen instellen

View File

@ -1,74 +0,0 @@
add developer_tools no Legg til
add change developer_tools no Legg til endre
add more developer_tools no Legg til mer
add new phrase developer_tools no Legg til ny frase
add phrase developer_tools no Legg til frase
allows you to add a single phrase developer_tools no Gir deg mulighet for å legge til en enkelt frase
application developer_tools no Program
back developer_tools no Tilbake
cancel developer_tools no Avbryt
change developer_tools no Endre
changelog entry has been added developer_tools no Det ble opprettet en post i endringsloggen.
changelogs developer_tools no Endringslogg
clears the internal buffer, all changes made sofar are lost developer_tools no Slett internt buffer. Alle endringer så langt går tapt.
create new language file developer_tools no Lag en ny språkfil
create sgml file developer_tools no Lag en SGML-fil
developer tools - preferences developer_tools no Utviklerverktøy - preferanser
developer_tools common no Verktøy for oversettelse
diary developer_tools no Dagbok
done developer_tools no Utført
download developer_tools no Last ned
download the lang-file to be saved in the apps setup-dir developer_tools no Last ned filen som skal lagres i programmets setup-mappe.
edit developer_tools no Endre
installed applications developer_tools no Installerte program
language file management developer_tools no Håndtere språkfiler
list changelogs developer_tools no List logg over endringer
load developer_tools no Last inn
loading source langfile developer_tools no Last inn kildefil
loading target langfile developer_tools no Last inn målfil
loads the selected lang-files, to be modified in the next steps developer_tools no Laster inn de valgte språkfiler som så kan endres i neste skritt
message developer_tools no Melding
message_id in english developer_tools no Meldingsident på engelsk
no file developer_tools no ingen fil
ok developer_tools no Ok
original developer_tools no Original
phrase in english (or empty if identical) developer_tools no Frase på engelsk (eller tom dersom dette er det samme)
preferences developer_tools no Preferanser
preferences have been updated developer_tools no Preferanser ble oppdatert
project developer_tools no Prosjekt
remove developer_tools no Fjerne
removed %1 phrases from the target language, as they are not present in the source language! developer_tools no Fjernet %1 fraser fra målspråket da disse ikke finnes i kildespråket!
returns to the application list, not saved changes get lost !!! developer_tools no Retur til programlisten. Lagrede endringer går ikke tapt !
revert developer_tools no Tilbakestill
saves the added/changed translations to an internal buffer, to be used in further steps developer_tools no Lagrer de endrede oversettelser til et internt buffer slik at disse kan benyttes videre.
search changelogs developer_tools no Søk i endringslogg
search for missing phrase developer_tools no Søk for manglende fraser
search new phrases developer_tools no Søk i nye fraser
searches the source-code for phrases not in the actual source-lang-file developer_tools no Søker i kilekoden etter fraser som ikke er i den aktuelle språkfilen.
select project developer_tools no Velg prosjekt
sf project tracker developer_tools no SF Projektoppfølging
sf project tracker preferences preferences no SF Projektoppfølging preferanser
source language developer_tools no Opprinnelig språk
sourceforge project id developer_tools no Sourceforge prosjektident
sourceforge project tracker developer_tools no Sourceforge Projektoppfølging
sourceforge project tracker preferences developer_tools no Sourceforge Projektoppfølging preferanser
step developer_tools no Steg
submit developer_tools no Send
target language developer_tools no Oversettes til språk
title developer_tools no Tittel
translate developer_tools no Oversett
translation developer_tools no Oversettelse
translation of phrase developer_tools no Oversettelse av frase
update developer_tools no Oppdater
update database developer_tools no Oppdater database
updates the translations of both lang-files in your database, so you can verify your work immediately developer_tools no Oppdaterer oversettelse av begge språkfiler i din database slik at du kan verifisere endringene umiddelbart.
version developer_tools no Versjon
write developer_tools no Lagre
write the lang-file to the apps setup-dir developer_tools no Skriv språkfilen til programmets setup-mappe
write to lang table developer_tools no Skriv til språkfilen
writing langfile for '%1' ... developer_tools no Skriver språkfil for '%1'
you have to [save] every manual change in the above fields, before you can go to the next step !!! developer_tools no Du må lagre hver manuell endring i feltene ovenfor før du går til neste steg !
you must a version developer_tools no Du må ha en versjon
you must enter a change developer_tools no Du må registrere en endring
you must select a project developer_tools no Du må velge et prosjekt
you need to set your preferences for this app developer_tools no Du må sette opp preferanser for dette programmet

Some files were not shown because too many files have changed in this diff Show More