remove phpgwapi and etemplate added to get it for history of api
Before Width: | Height: | Size: 45 KiB |
@ -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 = "''";
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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');
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -1 +0,0 @@
|
||||
|
@ -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',);
|
||||
|
@ -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')
|
||||
);
|
@ -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()
|
||||
)
|
||||
);
|
@ -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>
|
Before Width: | Height: | Size: 2.7 KiB |
@ -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>
|
@ -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>
|
@ -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><?php
|
||||
$setup_info['et_media']['name'] = 'et_media';
|
||||
$setup_info['et_media']['title'] = 'eT-Media';
|
||||
$setup_info['et_media']['version'] = '1.2';
|
||||
$setup_info['et_media']['app_order'] = 100; // at the end
|
||||
$setup_info['et_media']['tables'] = array('egw_et_media');
|
||||
$setup_info['et_media']['enable'] = 1;
|
||||
|
||||
/* Dependencies for this app to work */
|
||||
$setup_info['et_media']['depends'][] = array(
|
||||
'appname' => 'phpgwapi',
|
||||
'versions' => Array('1.2','1.3','1.4')
|
||||
);
|
||||
$setup_info['et_media']['depends'][] = array(
|
||||
'appname' => 'etemplate',
|
||||
'versions' => Array('1.2','1.3','1.4')
|
||||
);</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 "grid". The first cell may be
|
||||
a bit tricky to find, but will be highlighted when moving the mouse
|
||||
over it. On my computer this cell appears in pink as illustrated below:</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 "name": this is the same name as thee column in our
|
||||
egw_et_media table. This is important as those fields will be populated automatically for us by eGroupWare:</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 "type" is a
|
||||
Selectbox, the one used for "description" is a textarea. Note
|
||||
that the name of the input is "descr" and not description, as
|
||||
this is the name of the column in the table. Finally on the last row
|
||||
we have two widgets of type "Submitbutton" of names "read"
|
||||
and "save" and of corresponding label.</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 "Export XML". 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><?php
|
||||
$GLOBALS['phpgw_info']['flags'] = array(
|
||||
'currentapp' => 'et_media',
|
||||
'noheader' => True,
|
||||
'nonavbar' => True
|
||||
);
|
||||
include('../header.inc.php');
|
||||
$GLOBALS['egw']->redirect_link('/index.php', 'menuaction=et_media.ui_et_media.edit');
|
||||
</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 "Storage Object" (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 "Business Object" (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 "User Interface"
|
||||
(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 "inc" directory, called
|
||||
class.bo_et_media.inc.php and class.ui_et_media.inc.php.
|
||||
In this simple application, the bo layer will be fairly minimal,
|
||||
this said it is a good idea to create the application using the
|
||||
right standards from the start.</p>
|
||||
<p>Here is the file <b>/et_media/inc/class.bo_et_media.inc.php</b>:
|
||||
</p>
|
||||
<pre>
|
||||
<?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 <RalfBecker@outdoor-training.de>
|
||||
*/</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(
|
||||
'' => 'Select one ...',
|
||||
'cd' => 'Compact Disc',
|
||||
'dvd' => 'DVD',
|
||||
'book' => 'Book',
|
||||
'video' => 'Video Tape'
|
||||
);
|
||||
<span>/**
|
||||
* Constructor initializing so_sql
|
||||
*
|
||||
* @return so_et_media
|
||||
*/</span>
|
||||
function bo_et_media()
|
||||
{
|
||||
$this->so_sql('et_media','egw_et_media'); <span>// calling the constructor of the extended bo object</span>
|
||||
$this->empty_on_write = "''";
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<p>And finally the start of the
|
||||
<b>/et_media/inc/class.ui_et_media.inc.php</b>:</p>
|
||||
<pre>
|
||||
<?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 <RalfBecker@outdoor-training.de>
|
||||
*/</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' => True,
|
||||
);
|
||||
|
||||
<span>/**
|
||||
* Constructor
|
||||
*
|
||||
* @return ui_et_media
|
||||
*/</span>
|
||||
function ui_et_media()
|
||||
{
|
||||
$this->bo_et_media(); <span>// calling the constructor of the extended bo object</span>
|
||||
|
||||
$this->tmpl =& 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'] > 0)
|
||||
{
|
||||
$this->read($content);
|
||||
}
|
||||
<span>//echo "<p>edit: content ="; _debug_array($content);</span>
|
||||
$this->data_merge($content);
|
||||
<span>//echo "<p>edit: data ="; _debug_array($this->data);</span>
|
||||
|
||||
if (isset($content['save']))
|
||||
{
|
||||
$msg .= !$this->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->data + array(
|
||||
'msg' => $msg
|
||||
);
|
||||
$sel_options = array(
|
||||
'type' => $this->types
|
||||
);
|
||||
$this->tmpl->exec('et_media.ui_et_media.edit',$content,$sel_options,$no_button,array(
|
||||
'id' => $this->data['id']
|
||||
));
|
||||
}
|
||||
</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
|
||||
"msg" (to display messages), an HorizontalRule widget, and a
|
||||
Template widget: we will use a "sub template" called
|
||||
et_media.show.rows to display the rows of the search function. I have
|
||||
set the option of the template widget to "entry" as this is the
|
||||
name we will use to access to the data in the sub-template.
|
||||
</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 "Name" and
|
||||
"Author" 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 "Edit" and of name "edit[$row_cont[id]]"
|
||||
</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 "th" and the class of the
|
||||
content row is "row". eTemplate will automatically vary the
|
||||
colors of the "row" class to provide a nice visual effect.</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->edit();
|
||||
return;
|
||||
}
|
||||
array_unshift($found,false); <span>// change the array to start with index 1</span>
|
||||
$content = array(
|
||||
'msg' => lang('%1 matches on search criteria',count($found)-1),
|
||||
'entry' => $found,
|
||||
);
|
||||
$this->tmpl->read('et_media.show');
|
||||
|
||||
$this->tmpl->exec('et_media.ui_et_media.edit',$content);
|
||||
}
|
||||
}
|
||||
</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->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->init($found[0]); <span>// only one match --> show it in the editor</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->show($found); <span>// multiple matches --> 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 > 0)
|
||||
{
|
||||
$this->read(array('id' => $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 "show" 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->bo->so->delete($r_id);
|
||||
$content = array(); <span>// clear the content</span>
|
||||
}
|
||||
|
||||
$no_button = array( <span>// no delete button if id == 0 --> entry not saved</span>
|
||||
'delete' => !$this->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->db_key_cols[$this->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>
|
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 36 KiB |
@ -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
|
||||
?>
|
@ -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;
|
||||
}
|
||||
}
|
@ -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 {}
|
@ -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 {}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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'] = ' ';
|
||||
$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;
|
||||
}
|
||||
}
|
@ -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 {}
|
@ -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 {}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 {}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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 {}
|
@ -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
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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(' ',$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 ' ';
|
||||
}
|
||||
|
||||
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 .= '<'.$acc['account_lid'].'> ';
|
||||
// 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;
|
||||
}
|
||||
}
|
@ -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']));
|
||||
}
|
||||
}
|
@ -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 {}
|
@ -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 {}
|
@ -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 {}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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 .= ' ♦';
|
||||
}
|
||||
$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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
};
|
@ -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','&','"'),$id);
|
||||
}
|
||||
|
||||
function recode_id($id)
|
||||
{
|
||||
if (get_magic_quotes_gpc())
|
||||
{
|
||||
$id = stripslashes($id);
|
||||
}
|
||||
return str_replace(array('%5B','%5D'),array('[',']'),$id); // & + " 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;
|
||||
}
|
||||
}
|
@ -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('♥','(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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
?>
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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'] : ''));
|
@ -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(/&/g, '&');
|
||||
string = string.replace(/</g, '<');
|
||||
string = string.replace(/>/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';
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
download developer_tools bg Изтегляне
|
||||
remove developer_tools bg премахване
|
||||
translation developer_tools bg Превод
|
@ -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ó
|
@ -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
|
@ -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
|
@ -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
|
@ -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!
|
@ -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
|
@ -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
|
@ -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
|
@ -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 شما نیاز دارید که تنظیمات خود را برای برنامه مورد نظر انجام دهید
|
@ -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
|
@ -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
|
@ -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 हो गया
|
@ -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
|
@ -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
|
@ -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 !!!
|
@ -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
|
@ -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 עליך לקבוע את העדיפויות ליישום זה
|
@ -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 このアプリケーションのユーザ設定を行う必要があります
|
@ -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 이 응용프로그램의 환경설정을 반드시 하셔야합니다.
|
@ -1,3 +0,0 @@
|
||||
download developer_tools lo ດາວໂຫຼດ
|
||||
installed applications developer_tools lo ຕິດຕັ້ງ ແອັບພຼິເຄຊັນສ
|
||||
remove developer_tools lo ລຶບອອກ
|
@ -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
|
@ -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
|
@ -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
|