From 872fa0b72b94c5ef886ce012f456782b40606e07 Mon Sep 17 00:00:00 2001
From: Ralf Becker
Date: Sun, 14 Feb 2010 06:11:28 +0000
Subject: [PATCH 001/334] fixed stupid windows path: moved aspell_path config
to setup, vor obvious reasons
---
setup/inc/class.setup_process.inc.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/setup/inc/class.setup_process.inc.php b/setup/inc/class.setup_process.inc.php
index 4f9f64be5f..628d668c30 100755
--- a/setup/inc/class.setup_process.inc.php
+++ b/setup/inc/class.setup_process.inc.php
@@ -249,7 +249,7 @@ class setup_process
}
$current_config['files_dir'] = 'C:\\Program Files\\'.$egroupwareDirName.'\\'.$GLOBALS['egw_setup']->ConfigDomain.'\\files';
$current_config['backup_dir'] = 'C:\\Program Files\\'.$egroupwareDirName.'\\'.$GLOBALS['egw_setup']->ConfigDomain.'\\backup';
- $current_config['aspell_path'] = 'C:\Program Files\Aspell\bin\aspell.exe';
+ $current_config['aspell_path'] = 'C:\\Program Files\\Aspell\\bin\\aspell.exe';
}
// only set aspell path, if it's installed
if (!is_executable($current_config['aspell_path']))
From 0c640ed171fed220aa6609835835dbd52303d548 Mon Sep 17 00:00:00 2001
From: Ralf Becker
Date: Sun, 14 Feb 2010 06:27:54 +0000
Subject: [PATCH 002/334] support for 1.6.003
---
phpgwapi/setup/tables_update.inc.php | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/phpgwapi/setup/tables_update.inc.php b/phpgwapi/setup/tables_update.inc.php
index e8ffd70766..aa3e4ef4cb 100644
--- a/phpgwapi/setup/tables_update.inc.php
+++ b/phpgwapi/setup/tables_update.inc.php
@@ -33,6 +33,11 @@ function phpgwapi_upgrade1_6_002()
return $GLOBALS['setup_info']['phpgwapi']['currentver'] = '1.7.001';
}
+function phpgwapi_upgrade1_6_003()
+{
+ return $GLOBALS['setup_info']['phpgwapi']['currentver'] = '1.7.001';
+}
+
function phpgwapi_upgrade1_7_001()
{
$GLOBALS['egw_setup']->oProc->AddColumn('egw_sqlfs','fs_link',array(
From 0affaddfb286e5c21d8216cffafa0a5a9e8292bc Mon Sep 17 00:00:00 2001
From: Ralf Becker
Date: Mon, 15 Feb 2010 02:58:58 +0000
Subject: [PATCH 003/334] fix for Debian Bug#569677: egroupware-core: base
configuration fails with php error if egroupware-emailadmin is not installed
---
setup/inc/hook_config_validate.inc.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/setup/inc/hook_config_validate.inc.php b/setup/inc/hook_config_validate.inc.php
index 35e0d102ed..57cd5dac6a 100644
--- a/setup/inc/hook_config_validate.inc.php
+++ b/setup/inc/hook_config_validate.inc.php
@@ -43,7 +43,7 @@ function mail_server($settings)
{
$GLOBALS['config_error'] = lang('Missing or uncomplete mailserver configuration');
}
- if (@file_exists('../emailadmin/inc/class.emailadmin_bo.inc.php') && $GLOBALS['egw_setup']->table_exist(array('egw_emailadmin')) || true)
+ if (@file_exists('../emailadmin/inc/class.emailadmin_bo.inc.php') && $GLOBALS['egw_setup']->table_exist(array('egw_emailadmin')))
{
$emailadmin = new emailadmin_bo(-1,false); // false=no session stuff
if (is_object($emailadmin))
From dbeb104ed5ff852e7acba9d9a1ec52b6a1f613eb Mon Sep 17 00:00:00 2001
From: Ralf Becker
Date: Mon, 15 Feb 2010 04:35:32 +0000
Subject: [PATCH 004/334] changed rename to also rename in-active versions and
made mkdir_recursive private, as it is only a helper and no exported method
---
phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php b/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php
index eb6f818869..4b0d3cedae 100644
--- a/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php
+++ b/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php
@@ -548,12 +548,14 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url_from,$url_to)");
$path_from = parse_url($url_from,PHP_URL_PATH);
+ $from_dir = dirname($path_from);
$path_to = parse_url($url_to,PHP_URL_PATH);
$to_dir = dirname($path_to);
$operation = self::url2operation($url_from);
// we have to use array($class,'url_stat'), as $class.'::url_stat' requires PHP 5.2.3 and we currently only require 5.2+
- if (!($from_stat = call_user_func(array($class,'url_stat'),$path_from,0)) || !egw_vfs::check_access(dirname($path_from),egw_vfs::WRITABLE))
+ if (!($from_stat = call_user_func(array($class,'url_stat'),$path_from,0)) ||
+ !egw_vfs::check_access($from_dir,egw_vfs::WRITABLE,$from_dir_stat = call_user_func(array($class,'url_stat'),$from_dir,0)))
{
self::_remove_password($url_from);
self::_remove_password($url_to);
@@ -588,11 +590,12 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper
unset(self::$stat_cache[$path_from]);
unset(self::$stat_cache[$path_to]);
- $stmt = self::$pdo->prepare('UPDATE '.self::TABLE.' SET fs_dir=:fs_dir,fs_name=:fs_name WHERE fs_id=:fs_id');
+ $stmt = self::$pdo->prepare('UPDATE '.self::TABLE.' SET fs_dir=:fs_dir,fs_name=:fs_name WHERE fs_dir=:old_dir AND fs_name=:old_name');
$ok = $stmt->execute(array(
- 'fs_dir' => $to_dir_stat['ino'],
- 'fs_name' => egw_vfs::basename($path_to),
- 'fs_id' => $from_stat['ino'],
+ 'fs_dir' => $to_dir_stat['ino'],
+ 'fs_name' => egw_vfs::basename($path_to),
+ 'old_dir' => $from_dir_stat['ino'],
+ 'old_name' => $from_stat['name'],
));
unset($stmt);
@@ -614,7 +617,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper
/**
* due to problems with recursive directory creation, we have our own here
*/
- function mkdir_recursive($pathname, $mode, $depth=0)
+ private static function mkdir_recursive($pathname, $mode, $depth=0)
{
$maxdepth=10;
$depth2propagate = (int)$depth + 1;
From c70ff2e069dcc29beeb20cc584d55b4825ca2528 Mon Sep 17 00:00:00 2001
From: Ralf Becker
Date: Mon, 15 Feb 2010 06:02:36 +0000
Subject: [PATCH 005/334] fixed a strange PHP5.3 problem, it seems
call_user_func_array fails returning NULL for a static method with a var
parameter
---
phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php b/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php
index 4b0d3cedae..10cd385577 100644
--- a/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php
+++ b/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php
@@ -1679,7 +1679,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper
* @param array $props array or array with values for keys 'name', 'ns', 'val' (null to delete the prop)
* @return boolean true if props are updated, false otherwise (eg. ressource not found)
*/
- static function proppatch($path,array &$props)
+ static function proppatch($path,array $props)
{
if (self::LOG_LEVEL > 1) error_log(__METHOD__."(".array2string($path).','.array2string($props));
if (!is_numeric($path))
From 8d0c656df89fc072a9118fde500f889d03cf93f1 Mon Sep 17 00:00:00 2001
From: Nathan Gray
Date: Mon, 15 Feb 2010 20:40:34 +0000
Subject: [PATCH 006/334] Javascript fix for ajax select widget on IE
---
etemplate/js/ajax_select.js | 44 ++++++++++++++++++++++++++++++++++---
1 file changed, 41 insertions(+), 3 deletions(-)
diff --git a/etemplate/js/ajax_select.js b/etemplate/js/ajax_select.js
index 25c461f03a..1a1ed1b991 100644
--- a/etemplate/js/ajax_select.js
+++ b/etemplate/js/ajax_select.js
@@ -26,6 +26,8 @@ var current_app = 'etemplate';
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
@@ -212,6 +214,12 @@ 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);
@@ -224,18 +232,27 @@ 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 (e) {
+ } else if (typeof(e) == 'string' ) {
var id = e;
if(value) {
var value = value;
@@ -243,6 +260,9 @@ function change(e, value) {
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('['));
@@ -254,8 +274,14 @@ function change(e, value) {
* We check for Tab, Up and Down
*/
var interested = false;
+ var keycode = '';
for(var i = 0; i < no_search_keys.length; i++) {
- if(e.keyCode == no_search_keys[i]) {
+ if(e.which) {
+ keycode = e.which;
+ } else if(e && e.keyCode) {
+ keycode = e.keyCode;
+ }
+ if(keycode == no_search_keys[i]) {
interested = true;
break;
}
@@ -285,6 +311,18 @@ function change(e, 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
*/
From ea5535284fba82a0c87d6ed4cf53c0e58ec81fde Mon Sep 17 00:00:00 2001
From: Klaus Leithoff
Date: Tue, 16 Feb 2010 10:42:27 +0000
Subject: [PATCH 007/334] fix for addressbook hook_home problem; birthdays
where not displayed correctly anymore in home view
---
addressbook/inc/class.addressbook_bo.inc.php | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/addressbook/inc/class.addressbook_bo.inc.php b/addressbook/inc/class.addressbook_bo.inc.php
index 1461aa0862..7f01d79a53 100755
--- a/addressbook/inc/class.addressbook_bo.inc.php
+++ b/addressbook/inc/class.addressbook_bo.inc.php
@@ -146,8 +146,7 @@ class addressbook_bo extends addressbook_so
function __construct($contact_app='addressbook')
{
parent::__construct($contact_app);
-
- $this->now_su = new egw_time('now');
+ $this->now_su = egw_time::to('now','ts');
$this->prefs =& $GLOBALS['egw_info']['user']['preferences']['addressbook'];
// get the default addressbook from the users prefs
From 9d39f2ec989a670ed12c7b601a71047a7040d753 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Lehrke?=
Date: Tue, 16 Feb 2010 15:09:52 +0000
Subject: [PATCH 008/334] Fix newline issue
---
phpgwapi/inc/horde/Horde/String.php | 45 +++++++++++++++++++-------
phpgwapi/inc/horde/Horde/iCalendar.php | 2 +-
2 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/phpgwapi/inc/horde/Horde/String.php b/phpgwapi/inc/horde/Horde/String.php
index 1ff4021c21..237541a418 100644
--- a/phpgwapi/inc/horde/Horde/String.php
+++ b/phpgwapi/inc/horde/Horde/String.php
@@ -6,9 +6,9 @@ $GLOBALS['_HORDE_STRING_CHARSET'] = 'iso-8859-1';
* The String:: class provides static methods for charset and locale safe
* string manipulation.
*
- * $Horde: framework/Util/String.php,v 1.43.6.31 2008/10/23 21:28:38 jan Exp $
+ * $Horde: framework/Util/String.php,v 1.43.6.38 2009-09-15 16:36:14 jan Exp $
*
- * Copyright 2003-2008 The Horde Project (http://www.horde.org/)
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
@@ -86,6 +86,9 @@ class String {
}
/* If the from and to character sets are identical, return now. */
+ if ($from == $to) {
+ return $input;
+ }
$from = String::lower($from);
$to = String::lower($to);
if ($from == $to) {
@@ -94,6 +97,7 @@ class String {
if (is_array($input)) {
$tmp = array();
+ reset($input);
while (list($key, $val) = each($input)) {
$tmp[String::_convertCharset($key, $from, $to)] = String::convertCharset($val, $from, $to);
}
@@ -317,20 +321,40 @@ class String {
if (is_null($length)) {
$length = String::length($string, $charset) - $start;
}
+
if ($length == 0) {
return '';
}
+
+ /* Try mbstring. */
if (String::extensionExists('mbstring')) {
+ if (is_null($charset)) {
+ $charset = $GLOBALS['_HORDE_STRING_CHARSET'];
+ }
+ $old_error = error_reporting(0);
+ $ret = mb_substr($string, $start, $length, String::_mbstringCharset($charset));
+ error_reporting($old_error);
+ /* mb_substr() returns empty string on failure. */
+ if (strlen($ret)) {
+ return $ret;
+ }
+ }
+
+ /* Try iconv. */
+ if (function_exists('iconv_substr')) {
if (is_null($charset)) {
$charset = $GLOBALS['_HORDE_STRING_CHARSET'];
}
+
$old_error = error_reporting(0);
- $ret = mb_substr($string, $start, $length, String::_mbstringCharset($charset));
+ $ret = iconv_substr($string, $start, $length, $charset);
error_reporting($old_error);
- if (!empty($ret)) {
+ /* iconv_substr() returns false on failure. */
+ if ($ret !== false) {
return $ret;
}
}
+
return substr($string, $start, $length);
}
@@ -349,9 +373,6 @@ class String {
$charset = $GLOBALS['_HORDE_STRING_CHARSET'];
}
$charset = String::lower($charset);
- if ($charset == 'utf-8' || $charset == 'utf8') {
- return strlen(utf8_decode($string));
- }
if (String::extensionExists('mbstring')) {
$old_error = error_reporting(0);
$ret = mb_strlen($string, String::_mbstringCharset($charset));
@@ -360,6 +381,9 @@ class String {
return $ret;
}
}
+ if ($charset == 'utf-8' || $charset == 'utf8') {
+ return strlen(utf8_decode($string));
+ }
return strlen($string);
}
@@ -482,9 +506,9 @@ class String {
$line = String::substr($string, 0, $width, 'utf-8');
$string = String::substr($string, String::length($line, 'utf-8'), null, 'utf-8');
// Make sure didn't cut a word, unless we want hard breaks anyway.
- if (!$cut && preg_match('/^(.+?)(\s|\r?\n)/u', $string, $match)) {
+ if (!$cut && preg_match('/^(.+?)((\s|\r?\n).*)/us', $string, $match)) {
$line .= $match[1];
- $string = String::substr($string, String::length($match[1], 'utf-8'), null, 'utf-8');
+ $string = $match[2];
}
// Wrap at existing line breaks.
if (preg_match('/^(.*?)(\r?\n)(.*)$/u', $line, $match)) {
@@ -513,8 +537,7 @@ class String {
}
// Hard wrap if necessary.
if ($cut) {
- $wrapped .= String::substr($line, 0, $width, 'utf-8') . $break;
- $string = String::substr($line, $width, null, 'utf-8') . $string;
+ $wrapped .= $line . $break;
continue;
}
$wrapped .= $line;
diff --git a/phpgwapi/inc/horde/Horde/iCalendar.php b/phpgwapi/inc/horde/Horde/iCalendar.php
index b6140700a7..f6e99fd9df 100644
--- a/phpgwapi/inc/horde/Horde/iCalendar.php
+++ b/phpgwapi/inc/horde/Horde/iCalendar.php
@@ -1180,7 +1180,7 @@ class Horde_iCalendar {
case 'QUOTED-PRINTABLE':
if (!$this->isOldFormat())
{
- $enconding = false;
+ $encoding = false;
break;
}
$params_str .= ';ENCODING=' . $params['ENCODING'];
From 39666ba03b854e36474164de3c31613aa009e4bc Mon Sep 17 00:00:00 2001
From: Ralf Becker
Date: Tue, 16 Feb 2010 23:23:24 +0000
Subject: [PATCH 009/334] let link-entry display "appname: #id" for entries no
link title is available (eg. because they got deleted), makes sense eg. for
history logging
---
etemplate/inc/class.link_widget.inc.php | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/etemplate/inc/class.link_widget.inc.php b/etemplate/inc/class.link_widget.inc.php
index e900d6ccec..9595f705b4 100644
--- a/etemplate/inc/class.link_widget.inc.php
+++ b/etemplate/inc/class.link_widget.inc.php
@@ -371,8 +371,12 @@ class link_widget
$titles = array();
foreach(explode(',',$id) as $id)
{
- if ($id && ($title = egw_link::title($app,$id)))
+ if ($id)
{
+ if (!($title = egw_link::title($app,$id)))
+ {
+ $title = $app.': #'.$id;
+ }
$titles[$id] = $title;
}
}
From ab598b8fcbf6943cf74ed3c28a810128fc780d29 Mon Sep 17 00:00:00 2001
From: Ralf Becker
Date: Wed, 17 Feb 2010 00:55:43 +0000
Subject: [PATCH 010/334] fix for user changing the timezone while having an
edit popup open (unfixed the timestamps would change by the differenz of the
two timezones). This fix does eg. NOT fix history logging (depending on the
entry read before saving it), so it is better to handle the situation in the
UI code, thought this is better then not handling it at all
---
etemplate/inc/class.so_sql.inc.php | 50 +++++++++++++++++++++++++++---
1 file changed, 45 insertions(+), 5 deletions(-)
diff --git a/etemplate/inc/class.so_sql.inc.php b/etemplate/inc/class.so_sql.inc.php
index 4b54746a24..edd36a1cf8 100644
--- a/etemplate/inc/class.so_sql.inc.php
+++ b/etemplate/inc/class.so_sql.inc.php
@@ -166,7 +166,8 @@ class so_sql
* @param string $colum_prefix='' column prefix to automatic remove from the column-name, if the column name starts with it
* @param boolean $no_clone=false can we avoid to clone the db-object, default no
* new code using appnames and foreach(select(...,$app) can set it to avoid an extra instance of the db object
- * @param string $timestamp_type=null default null=leave them as is, 'ts'|'integer' use integer unix timestamps, 'object' use egw_time objects
+ * @param string $timestamp_type=null default null=leave them as is, 'ts'|'integer' use integer unix timestamps,
+ * 'object' use egw_time objects or 'string' use DB timestamp (Y-m-d H:i:s) string
*
* @return so_sql
*/
@@ -197,8 +198,22 @@ class so_sql
echo "
so_sql('$app','$table')
\n";
_debug_array($this);
}
- // set timestampt type and current time
- switch(($this->timestamp_type = $timestamp_type))
+ $this->set_times($timestamp_type);
+ }
+
+ /**
+ * Set class vars timestamp_type, now and tz_offset_s
+ *
+ * @param string|boolean $timestamp_type=false default false do NOT set time_stamptype,
+ * null=leave them as is, 'ts'|'integer' use integer unix timestamps, 'object' use egw_time objects,
+ * 'string' use DB timestamp (Y-m-d H:i:s) string
+ */
+ public function set_times($timestamp_type=false)
+ {
+ if ($timestamp_type !== false) $this->timestamp_type = $timestamp_type;
+
+ // set current time
+ switch($this->timestamp_type)
{
case 'object':
$this->now = new egw_time('now');
@@ -320,6 +335,10 @@ class so_sql
$this->data[$col] = $new[$col];
}
}
+ if (isset($new[self::USER_TIMEZONE_READ]))
+ {
+ $this->data[self::USER_TIMEZONE_READ] = $new[self::USER_TIMEZONE_READ];
+ }
if ((int) $this->debug >= 4) _debug_array($this->data);
}
@@ -419,6 +438,11 @@ class so_sql
return $this->data;
}
+
+ /**
+ * Name of automatically set user timezone field from read
+ */
+ const USER_TIMEZONE_READ = 'user_timezone_read';
/**
* reads row matched by key and puts all cols in the data array
@@ -514,6 +538,9 @@ class so_sql
}
$this->db2data();
+ // store user timezone used for reading
+ $this->data[self::USER_TIMEZONE_READ] = egw_time::$user_timezone->getName();
+
if ((int) $this->debug >= 4)
{
echo "data =\n"; _debug_array($this->data);
@@ -527,7 +554,7 @@ class so_sql
if ((int) $this->debug >= 4) echo "nothing found !!!
\n";
$this->db2data();
-
+
return False;
}
@@ -541,7 +568,20 @@ class so_sql
function save($keys=null,$extra_where=null)
{
if (is_array($keys) && count($keys)) $this->data_merge($keys);
-
+
+ // check if data contains user timezone during read AND user changed timezone since then
+ // --> load old timezone for the rest of this request
+ // this only a grude hack, better handle this situation in app code:
+ // history logging eg. depends on old data read before calling save, which is then in new timezone!
+ // anyway it's better fixing it here then not fixing it at all ;-)
+ if (isset($this->data[self::USER_TIMEZONE_READ]) && $this->data[self::USER_TIMEZONE_READ] != egw_time::$user_timezone->getName())
+ {
+ //echo "
".__METHOD__."() User change TZ since read! tz-read=".$this->data[self::USER_TIMEZONE_READ].' != current-tz='.egw_time::$user_timezone->getName()." --> fixing
\n";
+ error_log(__METHOD__."() User changed TZ since read! tz-read=".$this->data[self::USER_TIMEZONE_READ].' != current-tz='.egw_time::$user_timezone->getName()." --> fixing");
+ $GLOBALS['egw_info']['user']['preferences']['common']['tz'] = $this->data[self::USER_TIMEZONE_READ];
+ egw_time::setUserPrefs($this->data[self::USER_TIMEZONE_READ]);
+ $this->set_times();
+ }
$this->data2db();
if ((int) $this->debug >= 4) { echo "so_sql::save(".print_r($keys,true).") autoinc_id='$this->autoinc_id', data="; _debug_array($this->data); }
From d2d64a73fe20c1c14989e972af2aa64696a1968f Mon Sep 17 00:00:00 2001
From: Klaus Leithoff
Date: Wed, 17 Feb 2010 12:03:37 +0000
Subject: [PATCH 011/334] get rid of comma in full-emailadresses, as
imap_rfc_address_list assumes a new address to come after comma
---
addressbook/inc/class.addressbook_ui.inc.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/addressbook/inc/class.addressbook_ui.inc.php b/addressbook/inc/class.addressbook_ui.inc.php
index 986544ad88..3fb0538cd5 100644
--- a/addressbook/inc/class.addressbook_ui.inc.php
+++ b/addressbook/inc/class.addressbook_ui.inc.php
@@ -686,6 +686,7 @@ class addressbook_ui extends addressbook_bo
}
if($email)
{
+ $contact['n_fn'] = str_replace(',',' ',$contact['n_fn']);
$GLOBALS['egw']->js->set_onload("addEmail('".addslashes(
$contact['n_fn'] ? $contact['n_fn'].' <'.$email.'>' : $email)."');");
$Ok = true;
From 8204d84ca501920c192297b5418939d3f3d106d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Lehrke?=
Date: Wed, 17 Feb 2010 13:28:00 +0000
Subject: [PATCH 012/334] Enable proper 'refresh from server' again
---
phpgwapi/inc/horde/Horde/SyncML/Command/Alert.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/phpgwapi/inc/horde/Horde/SyncML/Command/Alert.php b/phpgwapi/inc/horde/Horde/SyncML/Command/Alert.php
index 89c2c0eac5..61e057ea3c 100644
--- a/phpgwapi/inc/horde/Horde/SyncML/Command/Alert.php
+++ b/phpgwapi/inc/horde/Horde/SyncML/Command/Alert.php
@@ -255,6 +255,7 @@ class Horde_SyncML_Command_Alert extends Horde_SyncML_Command {
case ALERT_REFRESH_FROM_SERVER:
$synctype = ALERT_REFRESH_FROM_SERVER;
$response = $anchormatch ? RESPONSE_OK : RESPONSE_REFRESH_REQUIRED;
+ $anchormatch = false;
break;
case ALERT_RESUME:
From 21ccdd5f288e11ef83577da78e83e39f5135bb56 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Lehrke?=
Date: Wed, 17 Feb 2010 13:29:28 +0000
Subject: [PATCH 013/334] Fix various synchronization issues (SyncML & CalDAV)
---
calendar/inc/class.calendar_bo.inc.php | 4 +
calendar/inc/class.calendar_boupdate.inc.php | 74 ++++++----
calendar/inc/class.calendar_groupdav.inc.php | 66 ++++++---
calendar/inc/class.calendar_ical.inc.php | 138 +++++++++++++-----
calendar/inc/class.calendar_sif.inc.php | 10 +-
calendar/inc/class.calendar_so.inc.php | 102 ++++++++-----
calendar/inc/class.calendar_ui.inc.php | 3 +-
calendar/templates/default/images/forward.gif | Bin 0 -> 319 bytes
calendar/templates/default/images/forward.png | Bin 0 -> 494 bytes
9 files changed, 264 insertions(+), 133 deletions(-)
create mode 100644 calendar/templates/default/images/forward.gif
create mode 100644 calendar/templates/default/images/forward.png
diff --git a/calendar/inc/class.calendar_bo.inc.php b/calendar/inc/class.calendar_bo.inc.php
index 08d45f45c6..9b759b0d6d 100644
--- a/calendar/inc/class.calendar_bo.inc.php
+++ b/calendar/inc/class.calendar_bo.inc.php
@@ -95,6 +95,7 @@ class calendar_bo
'R' => 'Rejected',
'T' => 'Tentative',
'U' => 'No Response',
+ 'D' => 'Delegated',
'G' => 'Group invitation',
);
/**
@@ -1349,6 +1350,9 @@ class calendar_bo
case 'U': // no response = unknown
$status = html::image('calendar','cnr-pending',$this->verbose_status[$status]);
break;
+ case 'D': // delegated
+ $status = html::image('calendar','forward',$this->verbose_status[$status]);
+ break;
case 'G': // group invitation
// Todo: Image, seems not to be used
$status = '('.$this->verbose_status[$status].')';
diff --git a/calendar/inc/class.calendar_boupdate.inc.php b/calendar/inc/class.calendar_boupdate.inc.php
index e4fe7a1639..c6cdc212a1 100644
--- a/calendar/inc/class.calendar_boupdate.inc.php
+++ b/calendar/inc/class.calendar_boupdate.inc.php
@@ -20,6 +20,7 @@ define('MSG_TENTATIVE',4);
define('MSG_ACCEPTED',5);
define('MSG_ALARM',6);
define('MSG_DISINVITE',7);
+define('MSG_DELEGATED',8);
/**
* Class to access AND manipulate all calendar data (business object)
@@ -493,7 +494,7 @@ class calendar_boupdate extends calendar_bo
// the following switch falls through all cases, as each included the following too
//
- $msg_is_response = $msg_type == MSG_REJECTED || $msg_type == MSG_ACCEPTED || $msg_type == MSG_TENTATIVE;
+ $msg_is_response = $msg_type == MSG_REJECTED || $msg_type == MSG_ACCEPTED || $msg_type == MSG_TENTATIVE || $msg_type == MSG_DELEGATED;
switch($ru = $part_prefs['calendar']['receive_updates'])
{
@@ -619,6 +620,12 @@ class calendar_boupdate extends calendar_bo
$msgtype = '"calendar";';
$method = 'REPLY';
break;
+ case MSG_DELEGATED:
+ $action = lang('Delegated');
+ $msg = 'Response';
+ $msgtype = '"calendar";';
+ $method = 'REPLY';
+ break;
case MSG_ALARM:
$action = lang('Alarm');
$msg = 'Alarm';
@@ -825,8 +832,16 @@ class calendar_boupdate extends calendar_bo
return false;
}
- // invalidate the read-cache if it contains the event we store now
- if ($event['id'] && $event['id'] == self::$cached_event['id']) self::$cached_event = array();
+ if ($event['id'])
+ {
+ // invalidate the read-cache if it contains the event we store now
+ if ($event['id'] == self::$cached_event['id']) self::$cached_event = array();
+ $old_event = $this->read($event['id'], $event['recurrence'], false, 'server');
+ }
+ else
+ {
+ $old_event = null;
+ }
$save_event = $event;
// we run all dates through date2ts, to adjust to server-time and the possible date-formats
@@ -858,8 +873,6 @@ class calendar_boupdate extends calendar_bo
}
$set_recurrences = false;
$set_recurrences_start = 0;
- $old_event = $this->read($event['id'], $event['recurrence']);
-
if (($cal_id = $this->so->save($event,$set_recurrences,$set_recurrences_start,0,$event['etag'])) && $set_recurrences && $event['recur_type'] != MCAL_RECUR_NONE)
{
$save_event['id'] = $cal_id;
@@ -1062,7 +1075,7 @@ class calendar_boupdate extends calendar_bo
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
"($cal_id, $uid, $status, $recur_date)");
}
- $old_event = $this->read($cal_id, $recur_date);
+ $old_event = $this->read($cal_id, $recur_date, false, 'server');
if (($Ok = $this->so->set_status($cal_id,is_numeric($uid)?'u':$uid[0],is_numeric($uid)?$uid:substr($uid,1),$status,$recur_date ? $this->date2ts($recur_date,true) : 0,$role)))
{
if ($updateTS) $GLOBALS['egw']->contenthistory->updateTimeStamp('calendar',$cal_id,'modify',time());
@@ -1071,6 +1084,7 @@ class calendar_boupdate extends calendar_bo
'R' => MSG_REJECTED,
'T' => MSG_TENTATIVE,
'A' => MSG_ACCEPTED,
+ 'D' => MSG_DELEGATED,
);
if (isset($status2msg[$status]))
{
@@ -1080,7 +1094,7 @@ class calendar_boupdate extends calendar_bo
}
// Update history
- if (!is_array($event)) $event = $this->read($cal_id);
+ $event = $this->read($cal_id, $recur_date, false, 'server');
$tracking = new calendar_tracking($this);
$tracking->track($event, $old_event);
@@ -1098,8 +1112,6 @@ class calendar_boupdate extends calendar_bo
*/
function delete($cal_id,$recur_date=0,$ignore_acl=false)
{
- $event = $this->read($cal_id,$recur_date);
-
if (!($event = $this->read($cal_id,$recur_date)) ||
!$ignore_acl && !$this->check_perms(EGW_ACL_DELETE,$event))
{
@@ -1111,10 +1123,6 @@ class calendar_boupdate extends calendar_bo
{
$this->so->delete($cal_id);
$GLOBALS['egw']->contenthistory->updateTimeStamp('calendar',$cal_id,'delete',time());
-
- // Update history
- $tracking = new calendar_tracking($this);
- $tracking->track($event, $event, null, true);
// delete all links to the event
egw_link::unlink(0,'calendar',$cal_id);
@@ -1448,6 +1456,7 @@ class calendar_boupdate extends calendar_bo
{
$matchingEvents = array();
$query = array();
+ $recur_date = 0;
if ($this->log)
{
@@ -1459,17 +1468,12 @@ class calendar_boupdate extends calendar_bo
{
if (isset($event['recurrence']))
{
- $recur_date = $event['recurrence'];
+ $recur_date = $this->date2usertime($event['recurrence']);
}
- else
+ elseif (isset($event['start']))
{
- $recur_date = $event['start'];
+ $recur_date = $this->date2usertime($event['start']);
}
- $recur_date = $this->date2usertime($recur_date);
- }
- else
- {
- $recur_date = 0;
}
if ($event['id'])
@@ -1501,13 +1505,14 @@ class calendar_boupdate extends calendar_bo
return $matchingEvents;
}
}
- if ($filter == 'exact' || $filter == 'check') return array();
+ if ($filter == 'exact') return array();
}
unset($event['id']);
if ($filter == 'master')
{
$query[] = 'recur_type!='. MCAL_RECUR_NONE;
+ $query['cal_recurrence'] = 0;
}
// only query calendars of users, we have READ-grants from
@@ -1611,7 +1616,7 @@ class calendar_boupdate extends calendar_bo
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
'(' . $event['uid'] . ')[EventUID]');
}
- if (isset($event['recurrence']))
+ if ($filter != 'master' && isset($event['recurrence']))
{
$query['cal_recurrence'] = $event['recurrence'];
}
@@ -1637,17 +1642,17 @@ class calendar_boupdate extends calendar_bo
foreach($foundEvents as $egwEvent)
{
- if (in_array($egwEvent['id'], $matchingEvents)) continue;
-
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
'[FOUND]: ' . array2string($egwEvent));
}
+ if (in_array($egwEvent['id'], $matchingEvents)) continue;
- if ($filter == 'chec' && !empty($event['uid']))
+ if (in_array($filter, array('exact', 'master')) && !empty($event['uid']))
{
$matchingEvents[] = $egwEvent['id']; // UID found
+ if ($filter = 'master') break;
continue;
}
@@ -1849,6 +1854,7 @@ class calendar_boupdate extends calendar_bo
}
}
$matchingEvents[] = $egwEvent['id']; // exact match
+ if ($filter = 'master') break;
}
// append pseudos as last entries
$matchingEvents = array_merge($matchingEvents, $pseudos);
@@ -1942,20 +1948,24 @@ class calendar_boupdate extends calendar_bo
in_array($event['recurrence'], $master_event['recur_exception']))
{
$type = 'SERIES-PSEUDO-EXCEPTION'; // could also be a real one
- $recurrence_event = $event;
+ $recurrence_event = $master_event;
+ $recurrence_event['start'] = $event['recurrence'];
+ $recurrence_event['end'] -= $master_event['start'] - $event['recurrence'];
break;
}
elseif (in_array($event['start'], $master_event['recur_exception']))
{
$type='SERIES-PSEUDO-EXCEPTION'; // new pseudo exception?
- $recurrence_event = $event;
+ $recurrence_event = $master_event;
+ $recurrence_event['start'] = $event['start'];
+ $recurrence_event['end'] -= $master_event['start'] - $event['start'];
break;
}
else
{
// try to find a suitable pseudo exception date
$egw_rrule = calendar_rrule::event2rrule($master_event, false);
- $egw_rrule->rewind();
+ $egw_rrule->current = clone $egw_rrule->time;
while ($egw_rrule->valid())
{
$occurrence = egw_time::to($egw_rrule->current(), 'server');
@@ -1967,7 +1977,9 @@ class calendar_boupdate extends calendar_bo
if ($event['start'] == $occurrence)
{
$type = 'SERIES-PSEUDO-EXCEPTION'; // let's try a pseudo exception
- $recurrence_event = $event;
+ $recurrence_event = $master_event;
+ $recurrence_event['start'] = $occurrence;
+ $recurrence_event['end'] -= $master_event['start'] - $occurrence;
break 2;
}
if (isset($event['recurrence']) && $event['recurrence'] == $occurrence)
@@ -2077,4 +2089,4 @@ class calendar_boupdate extends calendar_bo
}
}
}
-}
+}
\ No newline at end of file
diff --git a/calendar/inc/class.calendar_groupdav.inc.php b/calendar/inc/class.calendar_groupdav.inc.php
index 32d170f64d..5883a74643 100644
--- a/calendar/inc/class.calendar_groupdav.inc.php
+++ b/calendar/inc/class.calendar_groupdav.inc.php
@@ -110,10 +110,12 @@ class calendar_groupdav extends groupdav_handler
'daywise' => false,
'date_format' => 'server',
);
+ /*
if ($this->client_shared_uid_exceptions)
{
$cal_filters['query']['cal_reference'] = 0;
}
+ */
// process REPORT filters or multiget href's
if (($id || $options['root']['name'] != 'propfind') && !$this->_report_filters($options,$cal_filters,$id))
{
@@ -137,8 +139,17 @@ class calendar_groupdav extends groupdav_handler
if ($events)
{
// get all max user modified times at once
- foreach($events as &$event)
+ foreach($events as $k => &$event)
{
+ if ($this->client_shared_uid_exceptions &&
+ $event['reference'] &&
+ ($master = $this->bo->read($event['reference'], 0, false, 'server')) &&
+ array_search($event['recurrence'], $master['recur_exception']) !== false)
+ {
+ // this exception will be handled with the series master
+ unset($events[$k]);
+ continue;
+ }
$ids[] = $event['id'];
}
$max_user_modified = $this->bo->so->max_user_modified($ids);
@@ -350,22 +361,28 @@ class calendar_groupdav extends groupdav_handler
*/
private static function &get_series($uid,calendar_bo $bo=null)
{
- if (is_null($bo)) $bo = new calendar_bo();
+ if (is_null($bo)) $bo = new calendar_bopdate();
+
+ if (!($masterId = array_shift($bo->find_event(array('uid' => $uid), 'master')))
+ || !($master = $bo->read($masterId, 0, false, 'server')))
+ {
+ return array(); // should never happen
+ }
+
+ $exceptions = $master['recur_exception'];
$events =& $bo->search(array(
'query' => array('cal_uid' => $uid),
'daywise' => false,
'date_format' => 'server',
));
- $master = null;
+ $events = array_merge(array($master), $events);
foreach($events as $k => &$recurrence)
{
- if (!isset($master)) // first event is always the series master
- {
- $master =& $events[$k];
- //error_log('master: '.array2string($master));
- continue; // nothing to change
- }
+ //error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
+ // "($uid)[$k]:" . array2string($recurrence));
+ if (!$k) continue; // nothing to change
+
if ($recurrence['id'] != $master['id']) // real exception
{
//error_log('real exception: '.array2string($recurrence));
@@ -373,9 +390,9 @@ class calendar_groupdav extends groupdav_handler
// at least Lightning "understands" EXDATE as exception from what's included
// in the whole resource / VCALENDAR component
// not removing it causes Lightning to remove the exception itself
- if (($k = array_search($recurrence['recurrence'],$master['recur_exception'])) !== false)
+ if (($e = array_search($recurrence['recurrence'],$exceptions)) !== false)
{
- unset($master['recur_exception'][$k]);
+ unset($exceptions[$e]);
}
continue; // nothing to change
}
@@ -386,13 +403,14 @@ class calendar_groupdav extends groupdav_handler
unset($events[$k]); // no exception --> remove it
continue;
}
- // this is a virtual excetion now (no extra event/cal_id in DB)
+ // this is a virtual exception now (no extra event/cal_id in DB)
//error_log('virtual exception: '.array2string($recurrence));
$recurrence['recurrence'] = $recurrence['start'];
$recurrence['reference'] = $master['id'];
$recurrence['recur_type'] = MCAL_RECUR_NONE; // is set, as this is a copy of the master
// not for included exceptions (Lightning): $master['recur_exception'][] = $recurrence['start'];
}
+ $events[0]['recur_exception'] = $exceptions;
return $events;
}
@@ -416,10 +434,12 @@ class calendar_groupdav extends groupdav_handler
return $event;
}
$handler = $this->_get_handler();
- if (!is_numeric($id) && ($foundEntries = $handler->find_event($options['content'], 'check')))
+
+ if (!is_numeric($id) && ($foundEntries = $handler->find_event($options['content'], 'exact')))
{
$id = array_shift($foundEntries);
}
+
if (!($cal_id = $handler->importVCal($options['content'],is_numeric($id) ? $id : -1,
self::etag2value($this->http_if_match))))
{
@@ -448,14 +468,15 @@ class calendar_groupdav extends groupdav_handler
static function fix_series(array &$events)
{
foreach($events as $n => $event) error_log(__METHOD__." $n before: ".array2string($event));
- $master =& $events[0];
+ //$master =& $events[0];
$bo = new calendar_boupdate();
// get array with orginal recurrences indexed by recurrence-id
- $org_recurrences = array();
- foreach(self::get_series($master['uid'],$bo) as $event)
+ $org_recurrences = $exceptions = array();
+ foreach(self::get_series($events[0]['uid'],$bo) as $k => $event)
{
+ if (!$k) $master = $event;
if ($event['recurrence'])
{
$org_recurrences[$event['recurrence']] = $event;
@@ -463,9 +484,15 @@ class calendar_groupdav extends groupdav_handler
}
// assign cal_id's to already existing recurrences and evtl. re-add recur_exception to master
- foreach($events as &$recurrence)
+ foreach($events as $k => &$recurrence)
{
- if ($recurrence['id'] || !$recurrence['recurrence']) continue; // master
+ if (!$recurrence['recurrence'])
+ {
+ // master
+ $recurrence['id'] = $master['id'];
+ $master =& $events[$k];
+ continue;
+ }
// from now on we deal with exceptions
$org_recurrence = $org_recurrences[$recurrence['recurrence']];
@@ -478,12 +505,13 @@ class calendar_groupdav extends groupdav_handler
if ($recurrence['id'] != $master['id'])
{
error_log(__METHOD__.'() re-adding recur_exception '.$recurrence['recurrence'].' = '.date('Y-m-d H:i:s',$recurrence['recurrence']));
- $master['recur_exception'][] = $recurrence['recurrence'];
+ $exceptions[] = $recurrence['recurrence'];
}
// remove recurrence to be able to detect deleted exceptions
unset($org_recurrences[$recurrence['recurrence']]);
}
}
+ $master['recur_exception'] = array_merge($exceptions, $master['recur_exception']);
// delete not longer existing recurrences
foreach($org_recurrences as $org_recurrence)
diff --git a/calendar/inc/class.calendar_ical.inc.php b/calendar/inc/class.calendar_ical.inc.php
index 7a62111d79..167731fe1e 100644
--- a/calendar/inc/class.calendar_ical.inc.php
+++ b/calendar/inc/class.calendar_ical.inc.php
@@ -41,6 +41,7 @@ class calendar_ical extends calendar_boupdate
'A' => 'ACCEPTED',
'R' => 'DECLINED',
'T' => 'TENTATIVE',
+ 'D' => 'DELEGATED'
);
/**
* @var array conversation of the participant status ical => egw
@@ -51,6 +52,7 @@ class calendar_ical extends calendar_boupdate
'ACCEPTED' => 'A',
'DECLINED' => 'R',
'TENTATIVE' => 'T',
+ 'DELEGATED' => 'D',
);
/**
@@ -227,7 +229,7 @@ class calendar_ical extends calendar_boupdate
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
- "() User does not have the permission to read event $_id.\n",
+ '() User does not have the permission to read event ' . $event['id']. "\n",
3,$this->logfile);
}
return -1; // Permission denied
@@ -238,8 +240,8 @@ class calendar_ical extends calendar_boupdate
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
- "() Event $_id not found.\n",
- 3,$this->logfile);
+ "() Event $event not found.\n",
+ 3, $this->logfile);
}
}
continue;
@@ -342,15 +344,21 @@ class calendar_ical extends calendar_boupdate
$horde_vtimezone->parsevCalendar($vtimezone,'VTIMEZONE');
// DTSTART must be in local time!
$standard = $horde_vtimezone->findComponent('STANDARD');
- $dtstart = $standard->getAttribute('DTSTART');
- $dtstart = new egw_time($dtstart, egw_time::$server_timezone);
- $dtstart->setTimezone(self::$tz_cache[$tzid]);
- $standard->setAttribute('DTSTART', $dtstart->format('Ymd\THis'), array(), false);
+ if (is_a($standard, 'Horde_iCalendar'))
+ {
+ $dtstart = $standard->getAttribute('DTSTART');
+ $dtstart = new egw_time($dtstart, egw_time::$server_timezone);
+ $dtstart->setTimezone(self::$tz_cache[$tzid]);
+ $standard->setAttribute('DTSTART', $dtstart->format('Ymd\THis'), array(), false);
+ }
$daylight = $horde_vtimezone->findComponent('DAYLIGHT');
- $dtstart = $daylight->getAttribute('DTSTART');
- $dtstart = new egw_time($dtstart, egw_time::$server_timezone);
- $dtstart->setTimezone(self::$tz_cache[$tzid]);
- $daylight->setAttribute('DTSTART', $dtstart->format('Ymd\THis'), array(), false);
+ if (is_a($daylight, 'Horde_iCalendar'))
+ {
+ $dtstart = $daylight->getAttribute('DTSTART');
+ $dtstart = new egw_time($dtstart, egw_time::$server_timezone);
+ $dtstart->setTimezone(self::$tz_cache[$tzid]);
+ $daylight->setAttribute('DTSTART', $dtstart->format('Ymd\THis'), array(), false);
+ }
$vcal->addComponent($horde_vtimezone);
$vtimezones_added[] = $tzid;
}
@@ -396,6 +404,7 @@ class calendar_ical extends calendar_boupdate
sort($exceptions);
}
$event['recur_exception'] = $exceptions;
+ /*
// Adjust the event start -- must not be an exception
$length = $event['end'] - $event['start'];
$rriter = calendar_rrule::event2rrule($event, false, $tzid);
@@ -415,13 +424,21 @@ class calendar_ical extends calendar_boupdate
{
// the series dissolved completely into exceptions
continue;
- }
+ }*/
}
foreach ($egwSupportedFields as $icalFieldName => $egwFieldName)
{
- if (!isset($this->supportedFields[$egwFieldName])) continue;
-
+ if (!isset($this->supportedFields[$egwFieldName]))
+ {
+ if ($this->log)
+ {
+ error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
+ '(' . $event['id'] . ") [$icalFieldName] not supported\n",
+ 3,$this->logfile);
+ }
+ continue;
+ }
$values[$icalFieldName] = array();
switch ($icalFieldName)
{
@@ -928,11 +945,30 @@ class calendar_ical extends calendar_boupdate
{
if (!is_array($this->supportedFields)) $this->setSupportedFields();
- if (!($events = $this->icaltoegw($_vcalData,$cal_id,$etag,$recur_date)))
+ if (!($events = $this->icaltoegw($_vcalData)))
{
return false;
}
+ if ($cal_id > 0)
+ {
+ if (count($events) == 1)
+ {
+ $events[0]['id'] = $cal_id;
+ if (!is_null($etag)) $events[0]['etag'] = (int) $etag;
+ if ($recur_date) $events[0]['recurrence'] = $recur_date;
+ }
+ elseif (($foundEvent = $this->find_event(array('id' => $cal_id), 'exact')) &&
+ ($eventId = array_shift($foundEvent)) &&
+ ($egwEvent = $this->read($eventId)))
+ {
+ foreach ($events as $k => $event)
+ {
+ if (!isset($event['uid'])) $events[$k]['uid'] = $egwEvent['uid'];
+ }
+ }
+ }
+
// check if we are importing an event series with exceptions in CalDAV
// only first event / series master get's cal_id from URL
// other events are exceptions and need to be checked if they are new
@@ -947,13 +983,18 @@ class calendar_ical extends calendar_boupdate
foreach ($events as $event)
{
if ($this->so->isWholeDay($event)) $event['whole_day'] = true;
-
+ if (is_array($event['category']))
+ {
+ $event['category'] = $this->find_or_add_categories($event['category'],
+ isset($event['id']) ? $event['id'] : -1);
+ }
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
array2string($event)."\n",3,$this->logfile);
}
+ /*
if ($event['recur_type'] != MCAL_RECUR_NONE)
{
// Adjust the event start -- no exceptions before and at the start
@@ -987,7 +1028,7 @@ class calendar_ical extends calendar_boupdate
}
$event['recur_exception'] = $exceptions;
}
-
+ */
$updated_id = false;
$event_info = $this->get_event_info($event);
@@ -1066,11 +1107,11 @@ class calendar_ical extends calendar_boupdate
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
"() Restore status for $uid\n",3,$this->logfile);
}
- $event['participants']['uid'] = $event_info['stored_event']['participants'][$uid];
+ $event['participants'][$uid] = $event_info['stored_event']['participants'][$uid];
}
else
{
- $event['participants']['uid'] = calendar_so::combine_status('U');
+ $event['participants'][$uid] = calendar_so::combine_status('U');
}
}
}
@@ -1271,7 +1312,7 @@ class calendar_ical extends calendar_boupdate
if (is_array($days))
{
$recur_exceptions = array();
-
+ /*
if (!isset($days[$event_info['stored_event']['start']]) &&
$event_info['stored_event']['start'] < $event['start'])
{
@@ -1318,7 +1359,7 @@ class calendar_ical extends calendar_boupdate
$event['start'] = $startdate;
$event['end'] = $startdate + $length;
- }
+ } */
foreach ($event['recur_exception'] as $recur_exception)
{
@@ -1363,7 +1404,7 @@ class calendar_ical extends calendar_boupdate
$event_info['master_event']['recur_exception'] =
array_unique(array_merge($event_info['master_event']['recur_exception'],
array($event['recurrence'])));
-
+ /*
// Adjust the event start -- must not be an exception
$length = $event_info['master_event']['end'] - $event_info['master_event']['start'];
$rriter = calendar_rrule::event2rrule($event_info['master_event'], false);
@@ -1376,6 +1417,21 @@ class calendar_ical extends calendar_boupdate
// remove leading exceptions
if ($day < $newstart)
{
+ if (($foundEvents = $this->find_event(
+ array('uid' => $event_info['master_event']['uid'],
+ 'recurrence' => $day), 'exact')) &&
+ ($eventId = array_shift($foundEvents)) &&
+ ($exception = read($eventId, 0, 'server')))
+ {
+ // Unlink this exception
+ unset($exception['uid']);
+ $this->update($exception, true);
+ }
+ if ($event['recurrence'] == $day)
+ {
+ // Unlink this exception
+ unset($event['uid']);
+ }
unset($event_info['master_event']['recur_exception'][$key]);
}
}
@@ -1384,14 +1440,14 @@ class calendar_ical extends calendar_boupdate
{
$event_info['master_event']['start'] = $newstart;
$event_info['master_event']['end'] = $newstart + $length;
- $event_to_store = $event_info['master_event']; // prevent the master_event from being changed by the update method
- $this->server2usertime($event_to_store);
- $this->update($event_to_store, true);
- unset($event_to_store);
- }
+ }*/
$event['reference'] = $event_info['master_event']['id'];
$event['category'] = $event_info['master_event']['category'];
$event['owner'] = $event_info['master_event']['owner'];
+ $event_to_store = $event_info['master_event']; // prevent the master_event from being changed by the update method
+ $this->server2usertime($event_to_store);
+ $this->update($event_to_store, true);
+ unset($event_to_store);
}
$event_to_store = $event; // prevent $event from being changed by update method
@@ -1864,7 +1920,7 @@ class calendar_ical extends calendar_boupdate
}
}
- function icaltoegw($_vcalData, $cal_id=-1, $etag=null, $recur_date=0)
+ function icaltoegw($_vcalData)
{
if ($this->log)
{
@@ -1906,7 +1962,7 @@ class calendar_ical extends calendar_boupdate
{
if (is_a($component, 'Horde_iCalendar_vevent'))
{
- if (($event = $this->vevent2egw($component, $version, $this->supportedFields, $cal_id)))
+ if (($event = $this->vevent2egw($component, $version, $this->supportedFields)))
{
//common adjustments
if ($this->productManufacturer == '' && $this->productName == ''
@@ -1943,11 +1999,6 @@ class calendar_ical extends calendar_boupdate
date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
- // if cal_id, etag or recur_date is given, use/set it for 1. event
- if ($cal_id > 0) $events[0]['id'] = $cal_id;
- if (!is_null($etag)) $events[0]['etag'] = (int) $etag;
- if ($recur_date) $events[0]['recurrence'] = $recur_date;
-
return $events;
}
@@ -1957,11 +2008,10 @@ class calendar_ical extends calendar_boupdate
* @param array $component VEVENT
* @param string $version vCal version (1.0/2.0)
* @param array $supportedFields supported fields of the device
- * @param int $cal_id id of existing event in the content (only used to merge categories)
*
* @return array|boolean event on success, false on failure
*/
- function vevent2egw(&$component, $version, $supportedFields, $cal_id=-1)
+ function vevent2egw(&$component, $version, $supportedFields)
{
if (!is_a($component, 'Horde_iCalendar_vevent')) return false;
@@ -2353,7 +2403,7 @@ class calendar_ical extends calendar_boupdate
case 'CATEGORIES':
if ($attributes['value'])
{
- $vcardData['category'] = $this->find_or_add_categories(explode(',',$attributes['value']), $cal_id);
+ $vcardData['category'] = explode(',', $attributes['value']);
}
else
{
@@ -2369,6 +2419,7 @@ class calendar_ical extends calendar_boupdate
if (isset($attributes['params']['STATUS']))
{
$status = $this->status_ical2egw[strtoupper($attributes['params']['STATUS'])];
+ if (empty($status)) $status = 'X';
}
else
{
@@ -2599,8 +2650,6 @@ class calendar_ical extends calendar_boupdate
if ($this->calendarOwner) $event['owner'] = $this->calendarOwner;
- if ($cal_id > 0) $event['id'] = $cal_id;
-
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
@@ -2613,7 +2662,15 @@ class calendar_ical extends calendar_boupdate
function search($_vcalData, $contentID=null, $relax=false)
{
- if (($events = $this->icaltoegw($_vcalData,!is_null($contentID) ? $contentID : -1)))
+ if (is_null($contentID))
+ {
+ $eventId = -1;
+ }
+ else
+ {
+ $eventId = $contentID;
+ }
+ if (($events = $this->icaltoegw($_vcalData)))
{
// this function only supports searching a single event
if (count($events) == 1)
@@ -2621,6 +2678,7 @@ class calendar_ical extends calendar_boupdate
$filter = $relax ? 'relax' : 'check';
$event = array_shift($events);
if ($this->so->isWholeDay($event)) $event['whole_day'] = true;
+ $event['category'] = $this->find_or_add_categories($event['category'], $eventId);
if ($contentID) $event['id'] = $contentID;
return $this->find_event($event, $filter);
}
diff --git a/calendar/inc/class.calendar_sif.inc.php b/calendar/inc/class.calendar_sif.inc.php
index d5c70c8942..6551ebd2f9 100644
--- a/calendar/inc/class.calendar_sif.inc.php
+++ b/calendar/inc/class.calendar_sif.inc.php
@@ -430,6 +430,7 @@ class calendar_sif extends calendar_boupdate
return false;
}
+ /*
if ($event['recur_type'] != MCAL_RECUR_NONE)
{
// Adjust the event start -- no exceptions before and at the start
@@ -462,7 +463,7 @@ class calendar_sif extends calendar_boupdate
}
}
$event['recur_exception'] = $exceptions;
- }
+ } */
if ($recur_date) $event['recurrence'] = $recur_date;
$event_info = $this->get_event_info($event);
@@ -684,7 +685,7 @@ class calendar_sif extends calendar_boupdate
$event_info['master_event']['recur_exception'] =
array_unique(array_merge($event_info['master_event']['recur_exception'],
array($event['recurrence'])));
-
+ /*
// Adjust the event start -- must not be an exception
$length = $event_info['master_event']['end'] - $event_info['master_event']['start'];
$rriter = calendar_rrule::event2rrule($event_info['master_event'], false);
@@ -709,7 +710,7 @@ class calendar_sif extends calendar_boupdate
$this->server2usertime($event_to_store);
$this->update($event_to_store, true);
unset($event_to_store);
- }
+ } */
$event['reference'] = $event_info['master_event']['id'];
$event['category'] = $event_info['master_event']['category'];
$event['owner'] = $event_info['master_event']['owner'];
@@ -914,6 +915,7 @@ class calendar_sif extends calendar_boupdate
array2string($exceptions)."\n",3,$this->logfile);
}
$event['recur_exception'] = $exceptions;
+ /*
// Adjust the event start -- must not be an exception
$length = $event['end'] - $event['start'];
$rriter = calendar_rrule::event2rrule($event, false, $tzid);
@@ -927,7 +929,7 @@ class calendar_sif extends calendar_boupdate
// remove leading exceptions
if ($day <= $event['start']) unset($exceptions[$key]);
}
- $event['recur_exception'] = $exceptions;
+ $event['recur_exception'] = $exceptions; */
}
if ($this->uidExtension)
diff --git a/calendar/inc/class.calendar_so.inc.php b/calendar/inc/class.calendar_so.inc.php
index 1a5094a132..b198599cd0 100644
--- a/calendar/inc/class.calendar_so.inc.php
+++ b/calendar/inc/class.calendar_so.inc.php
@@ -44,6 +44,7 @@ define('REJECTED',0);
define('NO_RESPONSE',1);
define('TENTATIVE',2);
define('ACCEPTED',3);
+define('DELEGATED',4);
define('HOUR_s',60*60);
define('DAY_s',24*HOUR_s);
@@ -188,6 +189,18 @@ class calendar_so
$this->db->update($this->cal_table, array('cal_uid' => $event['uid']),
array('cal_id' => $event['id']),__LINE__,__FILE__,'calendar');
}
+ if ((int) $recur_date == 0 &&
+ $event['recur_type'] != MCAL_RECUR_NONE &&
+ !empty($event['recur_exception']))
+ {
+ sort($event['recur_exception']);
+ if ($event['recur_exception'][0] < $event['start'])
+ {
+ // leading exceptions => move start and end
+ $event['end'] -= $event['start'] - $event['recur_exception'][0];
+ $event['start'] = $event['recur_exception'][0];
+ }
+ }
}
// check if we have a real recurance, if not set $recur_date=0
@@ -377,6 +390,8 @@ class calendar_so
$where[] = "cal_status='T'"; break;
case 'rejected':
$where[] = "cal_status='R'"; break;
+ case 'delegated':
+ $where[] = "cal_status='D'"; break;
case 'all':
case 'owner':
break;
@@ -649,6 +664,8 @@ ORDER BY cal_user_type, cal_usre_id
$minimum_uid_length = 8;
}
+ $old_min = $old_duration = 0;
+
//echo '
'.__METHOD__.'('.array2string($event).",$change_since) event="; _debug_array($event);
//error_log(__METHOD__.'('.array2string($event).",$set_recurrences,$change_since,$etag)");
@@ -827,7 +844,7 @@ ORDER BY cal_user_type, cal_usre_id
// update start- and endtime if present in the event-array, evtl. we need to move all recurrences
if (isset($event['cal_start']) && isset($event['cal_end']))
{
- $this->move($cal_id,$event['cal_start'],$event['cal_end'],!$cal_id ? false : $change_since);
+ $this->move($cal_id,$event['cal_start'],$event['cal_end'],!$cal_id ? false : $change_since, $old_min, $old_min + $old_duration);
}
// update participants if present in the event-array
if (isset($event['cal_participants']))
@@ -1157,7 +1174,8 @@ ORDER BY cal_user_type, cal_usre_id
REJECTED => 'R',
NO_RESPONSE => 'U',
TENTATIVE => 'T',
- ACCEPTED => 'A'
+ ACCEPTED => 'A',
+ DELEGATED => 'D'
);
if (!(int)$cal_id || !(int)$user_id && $user_type != 'e')
{
@@ -1581,7 +1599,7 @@ ORDER BY cal_user_type, cal_usre_id
* @param int $start=0 if != 0: startdate of the search/list (servertime)
* @param int $end=0 if != 0: enddate of the search/list (servertime)
* @param string $filter='all' string filter-name: all (not rejected),
- * accepted, unknown, tentative, rejected,
+ * accepted, unknown, tentative, rejected, delegated
* rrule return array of remote exceptions in servertime
* tz_rrule/tz_only, return (only by) timezone transition affected entries
* map return array of dates with no pseudo exception
@@ -1607,15 +1625,46 @@ ORDER BY cal_user_type, cal_usre_id
$remote = in_array($filter, array('tz_rrule', 'rrule'));
$egw_rrule = calendar_rrule::event2rrule($event, false);
- $egw_rrule->rewind();
+ $egw_rrule->current = clone $egw_rrule->time;
if ($expand_all)
{
unset($event['recur_excpetion']);
$remote_rrule = calendar_rrule::event2rrule($event, false, $tz_id);
- $remote_rrule->rewind();
+ $remote_rrule->current = clone $remote_rrule->time;
}
while ($egw_rrule->valid())
{
+ while ($egw_rrule->exceptions &&
+ in_array($egw_rrule->current->format('Ymd'),$egw_rrule->exceptions))
+ {
+ if (in_array($filter, array('map','tz_map','rrule','tz_rrule')))
+ {
+ // real exception
+ $locts = (int)egw_time::to($egw_rrule->current(),'server');
+ if ($expand_all)
+ {
+ $remts = (int)egw_time::to($remote_rrule->current(),'server');
+ if ($remote)
+ {
+ $days[$locts]= $remts;
+ }
+ else
+ {
+ $days[$remts]= $locts;
+ }
+ }
+ else
+ {
+ $days[$locts]= $locts;
+ }
+ }
+ if ($expand_all)
+ {
+ $remote_rrule->next_no_exception();
+ }
+ $egw_rrule->next_no_exception();
+ if (!$egw_rrule->valid()) return $days;
+ }
$day = $egw_rrule->current();
$locts = (int)egw_time::to($day,'server');
$tz_exception = ($filter == 'tz_rrule');
@@ -1659,7 +1708,6 @@ ORDER BY cal_user_type, cal_usre_id
// '() status exception: ' . $day->format('Ymd\THis'));
if ($expand_all)
{
- $remts = (int)egw_time::to($remote_day,'server');
if ($filter == 'tz_only')
{
unset($days[$remts]);
@@ -1699,40 +1747,11 @@ ORDER BY cal_user_type, cal_usre_id
}
}
}
- do
+ if ($expand_all)
{
- $egw_rrule->next_no_exception();
- $day = $egw_rrule->current();
- if ($expand_all)
- {
- $remote_rrule->next_no_exception();
- $remts = (int)egw_time::to($remote_rrule->current(),'server');
- }
- $exception = $egw_rrule->exceptions &&
- in_array($day->format('Ymd'),$egw_rrule->exceptions);
- if (in_array($filter, array('map','tz_map','rrule','tz_rrule'))
- && $exception)
- {
- // real exception
- $locts = (int)egw_time::to($day,'ts');
- if ($expand_all)
- {
- if ($remote)
- {
- $days[$locts]= $remts;
- }
- else
- {
- $days[$remts]= $locts;
- }
- }
- else
- {
- $days[$locts]= $locts;
- }
- }
+ $remote_rrule->next_no_exception();
}
- while ($exception);
+ $egw_rrule->next_no_exception();
}
return $days;
}
@@ -1831,6 +1850,13 @@ ORDER BY cal_user_type, cal_usre_id
continue;
}
break;
+ case 'delegated':
+ if ($status != 'D')
+ {
+ unset($participants[$uid]);
+ continue;
+ }
+ break;
case 'default':
if ($status == 'R')
{
diff --git a/calendar/inc/class.calendar_ui.inc.php b/calendar/inc/class.calendar_ui.inc.php
index 2092dd515e..e9346b659d 100644
--- a/calendar/inc/class.calendar_ui.inc.php
+++ b/calendar/inc/class.calendar_ui.inc.php
@@ -146,7 +146,7 @@ class calendar_ui
$this->accountsel = $GLOBALS['egw']->uiaccountsel;
$this->categories = new categories($this->user,'calendar');
-
+
$this->common_prefs = &$GLOBALS['egw_info']['user']['preferences']['common'];
$this->cal_prefs = &$GLOBALS['egw_info']['user']['preferences']['calendar'];
$this->bo->check_set_default_prefs();
@@ -708,6 +708,7 @@ class calendar_ui
'accepted' => array(lang('Accepted'), lang('Show only accepted events')),
'unknown' => array(lang('Invitations'), lang('Show only invitations, not yet accepted or rejected')),
'tentative' => array(lang('Tentative'), lang('Show only tentative accepted events')),
+ 'delegated' => array(lang('Delegated'), lang('Show only delegated events')),
'rejected' => array(lang('Rejected'),lang('Show only rejected events')),
'owner' => array(lang('Owner too'),lang('Show also events just owned by selected user')),
'all' => array(lang('All incl. rejected'),lang('Show all status incl. rejected events')),
diff --git a/calendar/templates/default/images/forward.gif b/calendar/templates/default/images/forward.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7a5df0b7572acce25f3050e3e3c17a6d2601a9e8
GIT binary patch
literal 319
zcmZ?wbhEHb6E|9J%5>F;abPSbsh!FJPVdN
z6|HkFTIXK8#;bI#TiJTQ^3}c->-}ps2h?o~YuXXpvOTV4Yi#Sb#EzZm6AxufI+Qo%
zP|nmN|49dm{{)?jQWHy3QxwWGOEMJPJ$(Zh6o0ZXaxvI5=r8~Q$fFEw?g!=iq?Ap%+k(md=bD>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igJ=
z3mz`%)+>Sl00C}EL_t(2&yA74OB-<%z(3#bosCk|4)GT>L=Y*62qFo%Sm{y>mWG0p
zNVhKj1ByZxF@w7}b?)NeqP7UGZE+}~MG%6av>caK)1G(9d%1lD
zFgCX?Pm>A$xd9+ol0tzPrcyl}tsI{e0^2^HHUXk~9mlEQc(oh1h=_`Jw(-}wr1ZP|
zMQi=p1gQD}Eri4$YeYaRP%SY$KP2=k93K_;9%*yBu(RNs0Ipk^IXpTIX)ILJusoI;
z84s#1#b5S&jhZj)EcpGIeB
Date: Thu, 18 Feb 2010 23:32:25 +0000
Subject: [PATCH 014/334] Fix so sitemgr contact form shows contact's address
instead of current user
---
addressbook/inc/class.addressbook_tracking.inc.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addressbook/inc/class.addressbook_tracking.inc.php b/addressbook/inc/class.addressbook_tracking.inc.php
index 26b6d57926..b649412825 100644
--- a/addressbook/inc/class.addressbook_tracking.inc.php
+++ b/addressbook/inc/class.addressbook_tracking.inc.php
@@ -59,7 +59,7 @@ class addressbook_tracking extends bo_tracking
*
* @var boolean
*/
- var $prefer_user_as_sender = true;
+ var $prefer_user_as_sender = false;
/**
* Instance of the bocontacts class calling us
*
From 7304df7dcd00305d8e278e4c1621d13a9180892d Mon Sep 17 00:00:00 2001
From: Klaus Leithoff
Date: Fri, 19 Feb 2010 14:53:24 +0000
Subject: [PATCH 015/334] fix for a problem with IE7 and IE8(Compatibilitymode)
displaying Icons and text in Navbar
---
phpgwapi/templates/idots/css/traditional.css | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/phpgwapi/templates/idots/css/traditional.css b/phpgwapi/templates/idots/css/traditional.css
index 277a42b00a..1e3f3eb87d 100755
--- a/phpgwapi/templates/idots/css/traditional.css
+++ b/phpgwapi/templates/idots/css/traditional.css
@@ -322,7 +322,13 @@ body {
border:solid 1px #9c9c9c;
background-image: url(../images/background-icon-bar.png);
background-repeat: repeat-x;
- height: 45px;
+ overflow:visible;
+ height: 45px; /* prevents text line to show in IE7+8(Compatibilitymode) */
+}
+/* Star-Plus-HTML Hack fix for the above */
+*:first-child+html #divAppIconBar
+{
+ height: 60px;
}
#divAppTextBar
From ce7324f12fa35d2bf58a2733d9162b7a0d7e7dc7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Lehrke?=
Date: Fri, 19 Feb 2010 17:10:15 +0000
Subject: [PATCH 016/334] Fix daywise search
---
calendar/inc/class.calendar_bo.inc.php | 8 ++++++--
calendar/inc/class.calendar_so.inc.php | 2 +-
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/calendar/inc/class.calendar_bo.inc.php b/calendar/inc/class.calendar_bo.inc.php
index 9b759b0d6d..c229773809 100644
--- a/calendar/inc/class.calendar_bo.inc.php
+++ b/calendar/inc/class.calendar_bo.inc.php
@@ -16,6 +16,10 @@ if (!defined('ACL_TYPE_IDENTIFER')) // used to mark ACL-values for the debug_mes
define('ACL_TYPE_IDENTIFER','***ACL***');
}
+define('HOUR_s',60*60);
+define('DAY_s',24*HOUR_s);
+define('WEEK_s',7*DAY_s);
+
/**
* Gives read access to the calendar, but all events the user is not participating are private!
* Used by addressbook.
@@ -292,9 +296,9 @@ class calendar_bo
* filter string all (not rejected), accepted, unknown, tentative, rejected or hideprivate
* query string pattern so search for, if unset or empty all matching entries are returned (no search)
* Please Note: a search never returns repeating events more then once AND does not honor start+end date !!!
- * dayswise boolean on True it returns an array with YYYYMMDD strings as keys and an array with events
+ * daywise boolean on True it returns an array with YYYYMMDD strings as keys and an array with events
* (events spanning multiple days are returned each day again (!)) otherwise it returns one array with
- * the events (default), not honored in a search ==> always returns an array of events !
+ * the events (default), not honored in a search ==> always returns an array of events!
* date_format string date-formats: 'ts'=timestamp (default), 'array'=array, or string with format for date
* offset boolean/int false (default) to return all entries or integer offset to return only a limited result
* enum_recuring boolean if true or not set (default) or daywise is set, each recurence of a recuring events is returned,
diff --git a/calendar/inc/class.calendar_so.inc.php b/calendar/inc/class.calendar_so.inc.php
index b198599cd0..f5cf124b7b 100644
--- a/calendar/inc/class.calendar_so.inc.php
+++ b/calendar/inc/class.calendar_so.inc.php
@@ -1912,7 +1912,7 @@ ORDER BY cal_user_type, cal_usre_id
}
/**
- * Moves a datetime to the beginning og the day within timezone
+ * Moves a datetime to the beginning of the day within timezone
*
* @param egw_time &time the datetime entry
* @param string tz_id timezone
From e362a5b451cb61571988cd5f739f91ae839a9db6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Lehrke?=
Date: Fri, 19 Feb 2010 17:42:02 +0000
Subject: [PATCH 017/334] Use category names for history-log
---
calendar/inc/class.calendar_boupdate.inc.php | 2 ++
1 file changed, 2 insertions(+)
diff --git a/calendar/inc/class.calendar_boupdate.inc.php b/calendar/inc/class.calendar_boupdate.inc.php
index c6cdc212a1..e5e8822722 100644
--- a/calendar/inc/class.calendar_boupdate.inc.php
+++ b/calendar/inc/class.calendar_boupdate.inc.php
@@ -884,6 +884,8 @@ class calendar_boupdate extends calendar_bo
// Update history
$tracking = new calendar_tracking($this);
+ $event['category'] = implode(',', $this->get_categories($event['category']));
+ $old_event['category'] = implode(',', $this->get_categories($old_event['category']));
$tracking->track($event, $old_event);
return $cal_id;
From 3aa96a4a34c31f556f9bdd94ac7a683f01fc1838 Mon Sep 17 00:00:00 2001
From: Ralf Becker
Date: Sun, 21 Feb 2010 23:15:05 +0000
Subject: [PATCH 018/334] for xml: decode all entities, remove all
non-decodable entities, remove all html tags and encode <, > and & as
entities
---
etemplate/inc/class.bo_merge.inc.php | 27 ++++++++++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)
diff --git a/etemplate/inc/class.bo_merge.inc.php b/etemplate/inc/class.bo_merge.inc.php
index 476597e010..b08207e6d0 100644
--- a/etemplate/inc/class.bo_merge.inc.php
+++ b/etemplate/inc/class.bo_merge.inc.php
@@ -5,7 +5,7 @@
* @link http://www.egroupware.org
* @author Ralf Becker
* @package addressbook
- * @copyright (c) 2007-9 by Ralf Becker
+ * @copyright (c) 2007-10 by Ralf Becker
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
@@ -479,9 +479,30 @@ abstract class bo_merge
{
$replacements = $GLOBALS['egw']->translation->convert($replacements,$GLOBALS['egw']->translation->charset(),$charset);
}
- if ($is_xml) // zip'ed xml document (eg. OO) --> need to encode &,<,> to not mess up xml
+ if ($is_xml) // zip'ed xml document (eg. OO)
{
- $replacements = str_replace(array('&','&','<','>'),array('&','&','<','>'),$replacements);
+ // clean replacements from html or html-entities, which mess up xml
+ foreach($replacements as $name => &$value)
+ {
+ // decode html entities back to utf-8
+ if (strpos($value,'&') !== false)
+ {
+ $value = html_entity_decode($value,ENT_QUOTES,$charset);
+
+ // remove all non-decodable entities
+ if (strpos($value,'&') !== false)
+ {
+ $value = preg_replace('/&[^; ]+;/','',$value);
+ }
+ }
+ // remove all html tags, evtl. included
+ if (strpos($value,'<') !== false)
+ {
+ $value = strip_tags($value);
+ }
+ }
+ // now decode &, < and >, which need to be encoded as entities in xml
+ $replacements = str_replace(array('&','<','>'),array('&','<','>'),$replacements);
}
return str_replace(array_keys($replacements),array_values($replacements),$content);
}
From 08dbf52b66f57a629a652df5bbeee4c0e8a04d1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Lehrke?=
Date: Mon, 22 Feb 2010 10:02:33 +0000
Subject: [PATCH 019/334] Fix typos and code cleanup
---
calendar/inc/class.calendar_bo.inc.php | 19 +++++++++----------
calendar/inc/class.calendar_boupdate.inc.php | 15 +++++----------
calendar/inc/class.calendar_ical.inc.php | 2 +-
3 files changed, 15 insertions(+), 21 deletions(-)
diff --git a/calendar/inc/class.calendar_bo.inc.php b/calendar/inc/class.calendar_bo.inc.php
index c229773809..dfb3111216 100644
--- a/calendar/inc/class.calendar_bo.inc.php
+++ b/calendar/inc/class.calendar_bo.inc.php
@@ -639,7 +639,7 @@ class calendar_bo
$old_horizont = $this->config['horizont'];
$this->config['horizont'] = $new_horizont;
- // create further recurrences for all recuring and not yet (at the old horizont) ended events
+ // create further recurrences for all recurring and not yet (at the old horizont) ended events
if (($recuring = $this->so->unfinished_recuring($old_horizont)))
{
foreach($this->read(array_keys($recuring)) as $cal_id => $event)
@@ -660,7 +660,7 @@ class calendar_bo
}
/**
- * set all recurrences for an event until defined horizont $this->config['horizont']
+ * set all recurrences for an event until the defined horizont $this->config['horizont']
*
* This methods operates in usertime, while $this->config['horizont'] is in servertime!
*
@@ -715,7 +715,7 @@ class calendar_bo
function db2data(&$events,$date_format='ts')
{
if (!is_array($events)) echo "
bocal::db2data(\$events,$date_format) \$events is no array \n".function_backtrace()."
\n";
- foreach($events as $id => &$event)
+ foreach($events as &$event)
{
// convert timezone id of event to tzid (iCal id like 'Europe/Berlin')
if (!$event['tz_id'] || !($event['tzid'] = calendar_timezones::id2tz($event['tz_id'])))
@@ -732,7 +732,7 @@ class calendar_bo
// same with the recur exceptions
if (isset($event['recur_exception']) && is_array($event['recur_exception']))
{
- foreach($event['recur_exception'] as $n => &$date)
+ foreach($event['recur_exception'] as &$date)
{
$date = $this->date2usertime($date,$date_format);
}
@@ -740,7 +740,7 @@ class calendar_bo
// same with the alarms
if (isset($event['alarm']) && is_array($event['alarm']))
{
- foreach($event['alarm'] as $n => &$alarm)
+ foreach($event['alarm'] as &$alarm)
{
$alarm['time'] = $this->date2usertime($alarm['time'],$date_format);
}
@@ -769,7 +769,7 @@ class calendar_bo
* @param mixed $date=null date to specify a single event of a series
* @param boolean $ignore_acl should we ignore the acl, default False for a single id, true for multiple id's
* @param string $date_format='ts' date-formats: 'ts'=timestamp, 'server'=timestamp in servertime, 'array'=array, or string with date-format
- * @return boolean/array event or array of id => event pairs, false if the acl-check went wrong, null if $ids not found
+ * @return boolean|array event or array of id => event pairs, false if the acl-check went wrong, null if $ids not found
*/
function read($ids,$date=null,$ignore_acl=False,$date_format='ts')
{
@@ -985,7 +985,6 @@ class calendar_bo
$owner = $event['owner'];
$private = !$event['public'];
}
- $user = $GLOBALS['egw_info']['user']['account_id'];
$grants = $this->grants[$owner];
if (is_array($event) && $needed == EGW_ACL_READ)
{
@@ -996,11 +995,11 @@ class calendar_bo
{
foreach($event['participants'] as $uid => $accept)
{
- if ($uid == $user || $uid < 0 && in_array($user,$GLOBALS['egw']->accounts->members($uid,true)))
+ if ($uid == $this->user || $uid < 0 && in_array($this->user,$GLOBALS['egw']->accounts->members($uid,true)))
{
// if we are a participant, we have an implicite READ and PRIVAT grant
// exept the group gives its members only EGW_ACL_FREEBUSY and the participant is not the current user
- if ($this->grants[$uid] == EGW_ACL_FREEBUSY && $uid != $user) continue;
+ if ($this->grants[$uid] == EGW_ACL_FREEBUSY && $uid != $this->user) continue;
$grants |= EGW_ACL_READ | EGW_ACL_PRIVATE;
break;
@@ -1028,7 +1027,7 @@ class calendar_bo
}
else
{
- $access = $user == $owner || $grants & $needed && (!$private || $grants & EGW_ACL_PRIVATE);
+ $access = $this->user == $owner || $grants & $needed && (!$private || $grants & EGW_ACL_PRIVATE);
}
if ($this->debug && ($this->debug > 2 || $this->debug == 'check_perms'))
{
diff --git a/calendar/inc/class.calendar_boupdate.inc.php b/calendar/inc/class.calendar_boupdate.inc.php
index e5e8822722..aa67f173b1 100644
--- a/calendar/inc/class.calendar_boupdate.inc.php
+++ b/calendar/inc/class.calendar_boupdate.inc.php
@@ -1607,7 +1607,7 @@ class calendar_boupdate extends calendar_bo
$matchFields = array('priority', 'public', 'non_blocking', 'recurrence');
foreach ($matchFields as $key)
{
- if (!empty($event[$key])) $query['cal_'.$key] = $event[$key];
+ if (isset($event[$key])) $query['cal_'.$key] = $event[$key];
}
}
if (!empty($event['uid']))
@@ -1803,14 +1803,9 @@ class calendar_boupdate extends calendar_bo
// check exceptions
// $exceptions[$remote_ts] = $egw_ts
$exceptions = $this->so->get_recurrence_exceptions($egwEvent, $event['$tzid'], 0, 0, 'map');
- // remove leading exceptions
- foreach ($exceptions as $key => $day)
+ if (is_array($event['recur_exception']))
{
- if ($day <= $event['start']) unset($exceptions['key']);
- }
- if (is_array($event['recur_excpetion']))
- {
- foreach ($event['recur_excpetion'] as $key => $day)
+ foreach ($event['recur_exception'] as $key => $day)
{
if (isset($exceptions[$day]))
{
@@ -1832,14 +1827,14 @@ class calendar_boupdate extends calendar_bo
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
'() missing event[recur_exception]: ' .
- array2string($event['recur_excpetion']));
+ array2string($event['recur_exception']));
}
continue;
}
}
// check recurrence information
- foreach (array('recur_type', 'recur_interval') as $key)
+ foreach (array('recur_type', 'recur_interval', 'recur_enddate') as $key)
{
if (isset($event[$key])
&& $event[$key] != $egwEvent[$key])
diff --git a/calendar/inc/class.calendar_ical.inc.php b/calendar/inc/class.calendar_ical.inc.php
index 167731fe1e..04834cc128 100644
--- a/calendar/inc/class.calendar_ical.inc.php
+++ b/calendar/inc/class.calendar_ical.inc.php
@@ -2370,7 +2370,7 @@ class calendar_ical extends calendar_boupdate
}
break;
case 'SUMMARY':
- $vcardData['title'] = str_replace("\r\n", "\n", $attributes['value']);
+ $vcardData['title'] = str_replace("\r\n", "\n", $attributes['value']);
break;
case 'UID':
if (strlen($attributes['value']) >= $minimum_uid_length)
From fc3228806aa97c83ad21f989753feb6af37c8c0a Mon Sep 17 00:00:00 2001
From: Nathan Gray
Date: Mon, 22 Feb 2010 18:18:38 +0000
Subject: [PATCH 020/334] Fix infolog print view to only display the custom
fields allowed for that infolog type
---
infolog/setup/etemplates.inc.php | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/infolog/setup/etemplates.inc.php b/infolog/setup/etemplates.inc.php
index 5061508752..007e164feb 100644
--- a/infolog/setup/etemplates.inc.php
+++ b/infolog/setup/etemplates.inc.php
@@ -2,7 +2,7 @@
/**
* eGroupWare - eTemplates for Application infolog
* http://www.egroupware.org
- * generated by soetemplate::dump4setup() 2009-12-14 09:58
+ * generated by soetemplate::dump4setup() 2010-02-22 11:17
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package infolog
@@ -39,9 +39,9 @@ $templ_data[] = array('name' => 'infolog.edit.history','template' => '','lang' =
$templ_data[] = array('name' => 'infolog.edit.links','template' => '','lang' => '','group' => '0','version' => '1.3.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:6:{i:0;a:7:{s:1:"A";s:3:"100";s:2:"h1";s:13:",@status_only";s:2:"h2";s:13:",@status_only";s:2:"c1";s:2:"th";s:2:"c2";s:3:"row";s:2:"c4";s:2:"th";s:2:"c5";s:11:"row_off,top";}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:5:"label";s:16:"Create new links";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:3:{s:4:"type";s:7:"link-to";s:4:"span";s:3:"all";s:4:"name";s:7:"link_to";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:3;a:2:{s:1:"A";a:3:{s:4:"type";s:8:"link-add";s:4:"span";s:3:"all";s:4:"name";s:7:"link_to";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:4;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:5:"label";s:14:"Existing links";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:5;a:2:{s:1:"A";a:3:{s:4:"type";s:9:"link-list";s:4:"span";s:3:"all";s:4:"name";s:7:"link_to";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:5;s:4:"cols";i:2;s:4:"size";s:17:"100%,245,,,,,auto";s:7:"options";a:3:{i:0;s:4:"100%";i:1;s:3:"245";i:6;s:4:"auto";}}}','size' => '100%,245,,,,,auto','style' => '','modified' => '1075977056',);
-$templ_data[] = array('name' => 'infolog.edit.print','template' => '','lang' => '','group' => '0','version' => '1.7.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:22:{i:0;a:20:{s:1:"A";s:3:"103";s:1:"B";s:3:"260";s:1:"C";s:3:"140";s:2:"c3";s:3:"row";s:2:"c4";s:3:"row";s:2:"c5";s:3:"row";s:2:"c2";s:2:"th";s:2:"h2";s:2:"28";s:2:"h1";s:6:",!@msg";s:1:"D";s:3:"27%";s:3:"c18";s:6:"row_on";s:3:"c19";s:3:"row";s:3:"c20";s:3:"row";s:3:"c17";s:2:"th";s:2:"c7";s:2:"th";s:2:"h7";s:2:"10";s:3:"c21";s:3:"row";s:3:"h21";s:13:",!@info_owner";s:3:"h17";s:2:"10";s:3:"c10";s:2:"th";}i:1;a:4:{s:1:"A";a:5:{s:4:"type";s:4:"html";s:4:"span";s:13:"all,redItalic";s:5:"align";s:6:"center";s:4:"name";s:3:"msg";s:7:"no_lang";s:1:"1";}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:4:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";i:1;a:3:{s:4:"type";s:5:"image";s:4:"name";s:5:"print";s:7:"onclick";s:15:"window.print();";}i:2;a:4:{s:4:"type";s:5:"label";s:5:"label";s:4:"Type";s:4:"size";s:12:",,,info_type";s:8:"readonly";s:1:"1";}}s:1:"B";a:5:{s:4:"type";s:4:"hbox";s:4:"span";s:3:"all";s:4:"size";s:6:"2,,0,0";i:1;a:6:{s:4:"type";s:6:"select";s:4:"name";s:9:"info_type";s:8:"onchange";i:1;s:4:"help";s:46:"Type of the log-entry: Note, Phonecall or ToDo";s:7:"no_lang";s:1:"1";s:8:"readonly";s:1:"1";}i:2;a:4:{s:4:"type";s:3:"int";s:4:"name";s:11:"info_number";s:4:"span";s:7:",infoId";s:8:"readonly";s:1:"1";}}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:3:{s:4:"type";s:5:"label";s:5:"label";s:8:"Category";s:4:"size";s:11:",,,info_cat";}s:1:"B";a:5:{s:4:"type";s:10:"select-cat";s:4:"size";s:4:"None";s:4:"name";s:8:"info_cat";s:4:"help";s:32:"select a category for this entry";s:8:"readonly";s:1:"1";}s:1:"C";a:5:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";i:1;a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"Parent";}i:2;a:6:{s:4:"type";s:10:"link-entry";s:4:"size";s:7:"infolog";s:4:"name";s:14:"info_id_parent";s:5:"align";s:5:"right";s:4:"span";s:7:",noWrap";s:8:"readonly";s:1:"1";}s:4:"span";s:3:"all";}s:1:"D";a:1:{s:4:"type";s:5:"label";}}i:4;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:5:"label";s:7:"Contact";s:4:"size";s:12:",,,info_from";}s:1:"B";a:38:{s:4:"type";s:4:"vbox";s:4:"size";s:6:"2,,0,0";i:1;a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:6:"2,,0,0";i:1;a:4:{s:4:"type";s:10:"link-entry";s:4:"name";s:12:"info_contact";s:4:"span";s:7:",noWrap";s:8:"readonly";s:1:"1";}i:2;a:5:{s:4:"type";s:8:"checkbox";s:4:"name";s:16:"info_custom_from";s:8:"onchange";s:91:"document.getElementById(form::name(\'info_from\')).style.display=this.checked?\'block\':\'none\';";s:4:"help";s:31:"Check to specify custom contact";s:8:"readonly";s:1:"1";}}i:2;a:7:{s:4:"type";s:4:"text";s:4:"size";s:6:"36,255";s:4:"name";s:9:"info_from";s:4:"help";s:80:"Custom contact-information, leave emtpy to use information from most recent link";s:4:"blur";s:11:"@blur_title";s:4:"span";s:21:",$cont[hide_from_css]";s:8:"readonly";s:1:"1";}i:3;a:1:{s:4:"type";s:5:"label";}i:4;a:1:{s:4:"type";s:5:"label";}i:5;a:1:{s:4:"type";s:5:"label";}i:6;a:1:{s:4:"type";s:5:"label";}i:7;a:1:{s:4:"type";s:5:"label";}i:8;a:1:{s:4:"type";s:5:"label";}i:9;a:1:{s:4:"type";s:5:"label";}i:10;a:1:{s:4:"type";s:5:"label";}i:11;a:1:{s:4:"type";s:5:"label";}i:12;a:1:{s:4:"type";s:5:"label";}i:13;a:1:{s:4:"type";s:5:"label";}i:14;a:1:{s:4:"type";s:5:"label";}i:15;a:1:{s:4:"type";s:5:"label";}i:16;a:1:{s:4:"type";s:5:"label";}i:17;a:1:{s:4:"type";s:5:"label";}i:18;a:1:{s:4:"type";s:5:"label";}i:19;a:1:{s:4:"type";s:5:"label";}i:20;a:1:{s:4:"type";s:5:"label";}i:21;a:1:{s:4:"type";s:5:"label";}i:22;a:1:{s:4:"type";s:5:"label";}i:23;a:1:{s:4:"type";s:5:"label";}i:24;a:1:{s:4:"type";s:5:"label";}i:25;a:1:{s:4:"type";s:5:"label";}i:26;a:1:{s:4:"type";s:5:"label";}i:27;a:1:{s:4:"type";s:5:"label";}i:28;a:1:{s:4:"type";s:5:"label";}i:29;a:1:{s:4:"type";s:5:"label";}i:30;a:1:{s:4:"type";s:5:"label";}i:31;a:1:{s:4:"type";s:5:"label";}i:32;a:1:{s:4:"type";s:5:"label";}i:33;a:1:{s:4:"type";s:5:"label";}i:34;a:1:{s:4:"type";s:5:"label";}i:35;a:1:{s:4:"type";s:5:"label";}i:36;a:1:{s:4:"type";s:5:"label";}}s:1:"C";a:3:{s:4:"type";s:5:"label";s:4:"size";s:12:",,,info_addr";s:5:"label";s:11:"Phone/Email";}s:1:"D";a:6:{s:4:"type";s:4:"text";s:4:"size";s:6:"30,255";s:4:"name";s:9:"info_addr";s:4:"help";s:76:"Custom contact-address, leave empty to use information from most recent link";s:4:"span";s:15:",inputFullWidth";s:8:"readonly";s:1:"1";}}i:5;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:5:"label";s:7:"Subject";s:4:"size";s:15:",,,info_subject";}s:1:"B";a:6:{s:4:"type";s:4:"text";s:4:"size";s:6:"80,255";s:4:"span";s:5:"all,b";s:4:"name";s:12:"info_subject";s:4:"help";s:29:"a short subject for the entry";s:8:"readonly";s:1:"1";}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:1:{s:4:"type";s:5:"label";}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:7;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:5:"label";s:11:"Description";}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:8;a:4:{s:1:"A";a:6:{s:4:"type";s:8:"textarea";s:7:"no_lang";s:1:"1";s:4:"name";s:8:"info_des";s:4:"help";s:44:"enter a textual description of the log-entry";s:4:"span";s:15:"all,description";s:8:"readonly";s:1:"1";}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:1:{s:4:"type";s:5:"label";}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:10;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:5:"label";s:12:"customfields";}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:11;a:4:{s:1:"A";a:3:{s:4:"type";s:12:"customfields";s:4:"span";s:3:"all";s:8:"readonly";s:1:"1";}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:12;a:4:{s:1:"A";a:3:{s:4:"type";s:8:"template";s:4:"span";s:3:"all";s:4:"name";s:26:"infolog.edit.print.project";}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:13;a:4:{s:1:"A";a:3:{s:4:"type";s:8:"template";s:4:"name";s:24:"infolog.edit.print.links";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:14;a:4:{s:1:"A";a:1:{s:4:"type";s:5:"label";}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:15;a:4:{s:1:"A";a:3:{s:4:"type";s:8:"template";s:4:"name";s:29:"infolog.edit.print.delegation";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:16;a:4:{s:1:"A";a:1:{s:4:"type";s:5:"label";}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:17;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:5:"label";s:21:"Dates, Status, Access";}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:18;a:4:{s:1:"A";a:4:{s:4:"type";s:5:"label";s:5:"label";s:9:"Startdate";s:4:"size";s:17:",,,info_startdate";s:8:"readonly";s:1:"1";}s:1:"B";a:5:{s:4:"type";s:9:"date-time";s:4:"size";s:2:",2";s:4:"name";s:14:"info_startdate";s:4:"help";s:115:"when should the ToDo or Phonecall be started, it shows up from that date in the filter open or own open (startpage)";s:8:"readonly";s:1:"1";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:5:"label";s:7:"Enddate";s:4:"size";s:15:",,,info_enddate";}s:1:"D";a:4:{s:4:"type";s:4:"date";s:4:"name";s:12:"info_enddate";s:4:"help";s:49:"til when should the ToDo or Phonecall be finished";s:8:"readonly";s:1:"1";}}i:19;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:5:"label";s:6:"Status";s:4:"size";s:14:",,,info_status";}s:1:"B";a:5:{s:4:"type";s:6:"select";s:4:"name";s:11:"info_status";s:4:"help";s:12:"@status_help";s:8:"onchange";s:183:"if (this.value==\'done\' || this.value==\'billed\') set_element(this.form,\'exec[info_percent]\',\'100\'); else if (this.value==\'not-started\') set_element(this.form,\'exec[info_percent]\',\'0\');";s:8:"readonly";s:1:"1";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:5:"label";s:9:"Completed";s:4:"size";s:15:",,,info_percent";}s:1:"D";a:5:{s:4:"type";s:14:"select-percent";s:4:"name";s:12:"info_percent";s:4:"help";s:17:"Percent completed";s:8:"onchange";s:570:"if (this.value==100 && this.form[\'exec[info_status]\'].value != \'done\' && this.form[\'exec[info_status]\'].value != \'billed\' && this.form[\'exec[info_status]\'].value != \'cancelled\') this.form[\'exec[info_status]\'].value=\'done\'; else if (this.value != 100 && this.form[\'exec[info_status]\'].value != \'cancelled\') this.form[\'exec[info_status]\'].value=this.value != 0 ? \'ongoing\' : \'not-started\'; else if (this.value==0 && this.form[\'exec[info_status]\'].value != \'cancelled\' && this.form[\'exec[info_status]\'].value != \'offer\') this.form[\'exec[info_status]\'].value=\'not-started\'; ";s:8:"readonly";s:1:"1";}}i:20;a:4:{s:1:"A";a:4:{s:4:"type";s:5:"label";s:4:"size";s:21:",,,info_datecompleted";s:5:"label";s:14:"Date completed";s:8:"readonly";s:1:"1";}s:1:"B";a:4:{s:4:"type";s:9:"date-time";s:4:"name";s:18:"info_datecompleted";s:4:"help";s:84:"Date completed (leave it empty to have it automatic set if status is done or billed)";s:8:"readonly";s:1:"1";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:5:"label";s:7:"Private";s:4:"size";s:14:",,,info_access";}s:1:"D";a:5:{s:4:"type";s:8:"checkbox";s:4:"size";s:14:"private,public";s:4:"name";s:11:"info_access";s:4:"help";s:87:"should this entry only be visible to you and people you grant privat access via the ACL";s:8:"readonly";s:1:"1";}}i:21;a:4:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:5:"Owner";}s:1:"B";a:3:{s:4:"type";s:14:"select-account";s:4:"name";s:10:"info_owner";s:8:"readonly";s:1:"1";}s:1:"C";a:2:{s:4:"type";s:5:"label";s:5:"label";s:13:"Last modified";}s:1:"D";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:5:"2,0,0";i:1;a:3:{s:4:"type";s:14:"select-account";s:4:"name";s:13:"info_modifier";s:8:"readonly";s:1:"1";}i:2;a:4:{s:4:"type";s:9:"date-time";s:4:"span";s:10:",lpadding5";s:4:"name";s:17:"info_datemodified";s:8:"readonly";s:1:"1";}}}}s:4:"rows";i:21;s:4:"cols";i:4;s:4:"size";s:4:"100%";s:7:"options";a:1:{i:0;s:4:"100%";}}}','size' => '100%','style' => '.hideFrom input { display: none; }
+$templ_data[] = array('name' => 'infolog.edit.print','template' => '','lang' => '','group' => '0','version' => '1.7.002','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:22:{i:0;a:20:{s:1:"A";s:3:"103";s:1:"B";s:3:"260";s:1:"C";s:3:"140";s:2:"c3";s:3:"row";s:2:"c4";s:3:"row";s:2:"c5";s:3:"row";s:2:"c2";s:2:"th";s:2:"h2";s:2:"28";s:2:"h1";s:6:",!@msg";s:1:"D";s:3:"27%";s:3:"c18";s:6:"row_on";s:3:"c19";s:3:"row";s:3:"c20";s:3:"row";s:3:"c17";s:2:"th";s:2:"c7";s:2:"th";s:2:"h7";s:2:"10";s:3:"c21";s:3:"row";s:3:"h21";s:13:",!@info_owner";s:3:"h17";s:2:"10";s:3:"c10";s:2:"th";}i:1;a:4:{s:1:"A";a:5:{s:4:"type";s:4:"html";s:4:"span";s:13:"all,redItalic";s:5:"align";s:6:"center";s:4:"name";s:3:"msg";s:7:"no_lang";s:1:"1";}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:4:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";i:1;a:3:{s:4:"type";s:5:"image";s:4:"name";s:5:"print";s:7:"onclick";s:15:"window.print();";}i:2;a:4:{s:4:"type";s:5:"label";s:5:"label";s:4:"Type";s:4:"size";s:12:",,,info_type";s:8:"readonly";s:1:"1";}}s:1:"B";a:5:{s:4:"type";s:4:"hbox";s:4:"span";s:3:"all";s:4:"size";s:6:"2,,0,0";i:1;a:6:{s:4:"type";s:6:"select";s:4:"name";s:9:"info_type";s:8:"onchange";i:1;s:4:"help";s:46:"Type of the log-entry: Note, Phonecall or ToDo";s:7:"no_lang";s:1:"1";s:8:"readonly";s:1:"1";}i:2;a:4:{s:4:"type";s:3:"int";s:4:"name";s:11:"info_number";s:4:"span";s:7:",infoId";s:8:"readonly";s:1:"1";}}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:3:{s:4:"type";s:5:"label";s:5:"label";s:8:"Category";s:4:"size";s:11:",,,info_cat";}s:1:"B";a:5:{s:4:"type";s:10:"select-cat";s:4:"size";s:4:"None";s:4:"name";s:8:"info_cat";s:4:"help";s:32:"select a category for this entry";s:8:"readonly";s:1:"1";}s:1:"C";a:5:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";i:1;a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"Parent";}i:2;a:6:{s:4:"type";s:10:"link-entry";s:4:"size";s:7:"infolog";s:4:"name";s:14:"info_id_parent";s:5:"align";s:5:"right";s:4:"span";s:7:",noWrap";s:8:"readonly";s:1:"1";}s:4:"span";s:3:"all";}s:1:"D";a:1:{s:4:"type";s:5:"label";}}i:4;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:5:"label";s:7:"Contact";s:4:"size";s:12:",,,info_from";}s:1:"B";a:38:{s:4:"type";s:4:"vbox";s:4:"size";s:6:"2,,0,0";i:1;a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:6:"2,,0,0";i:1;a:4:{s:4:"type";s:10:"link-entry";s:4:"name";s:12:"info_contact";s:4:"span";s:7:",noWrap";s:8:"readonly";s:1:"1";}i:2;a:5:{s:4:"type";s:8:"checkbox";s:4:"name";s:16:"info_custom_from";s:8:"onchange";s:91:"document.getElementById(form::name(\'info_from\')).style.display=this.checked?\'block\':\'none\';";s:4:"help";s:31:"Check to specify custom contact";s:8:"readonly";s:1:"1";}}i:2;a:7:{s:4:"type";s:4:"text";s:4:"size";s:6:"36,255";s:4:"name";s:9:"info_from";s:4:"help";s:80:"Custom contact-information, leave emtpy to use information from most recent link";s:4:"blur";s:11:"@blur_title";s:4:"span";s:21:",$cont[hide_from_css]";s:8:"readonly";s:1:"1";}i:3;a:1:{s:4:"type";s:5:"label";}i:4;a:1:{s:4:"type";s:5:"label";}i:5;a:1:{s:4:"type";s:5:"label";}i:6;a:1:{s:4:"type";s:5:"label";}i:7;a:1:{s:4:"type";s:5:"label";}i:8;a:1:{s:4:"type";s:5:"label";}i:9;a:1:{s:4:"type";s:5:"label";}i:10;a:1:{s:4:"type";s:5:"label";}i:11;a:1:{s:4:"type";s:5:"label";}i:12;a:1:{s:4:"type";s:5:"label";}i:13;a:1:{s:4:"type";s:5:"label";}i:14;a:1:{s:4:"type";s:5:"label";}i:15;a:1:{s:4:"type";s:5:"label";}i:16;a:1:{s:4:"type";s:5:"label";}i:17;a:1:{s:4:"type";s:5:"label";}i:18;a:1:{s:4:"type";s:5:"label";}i:19;a:1:{s:4:"type";s:5:"label";}i:20;a:1:{s:4:"type";s:5:"label";}i:21;a:1:{s:4:"type";s:5:"label";}i:22;a:1:{s:4:"type";s:5:"label";}i:23;a:1:{s:4:"type";s:5:"label";}i:24;a:1:{s:4:"type";s:5:"label";}i:25;a:1:{s:4:"type";s:5:"label";}i:26;a:1:{s:4:"type";s:5:"label";}i:27;a:1:{s:4:"type";s:5:"label";}i:28;a:1:{s:4:"type";s:5:"label";}i:29;a:1:{s:4:"type";s:5:"label";}i:30;a:1:{s:4:"type";s:5:"label";}i:31;a:1:{s:4:"type";s:5:"label";}i:32;a:1:{s:4:"type";s:5:"label";}i:33;a:1:{s:4:"type";s:5:"label";}i:34;a:1:{s:4:"type";s:5:"label";}i:35;a:1:{s:4:"type";s:5:"label";}i:36;a:1:{s:4:"type";s:5:"label";}}s:1:"C";a:3:{s:4:"type";s:5:"label";s:4:"size";s:12:",,,info_addr";s:5:"label";s:11:"Phone/Email";}s:1:"D";a:6:{s:4:"type";s:4:"text";s:4:"size";s:6:"30,255";s:4:"name";s:9:"info_addr";s:4:"help";s:76:"Custom contact-address, leave empty to use information from most recent link";s:4:"span";s:15:",inputFullWidth";s:8:"readonly";s:1:"1";}}i:5;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:5:"label";s:7:"Subject";s:4:"size";s:15:",,,info_subject";}s:1:"B";a:6:{s:4:"type";s:4:"text";s:4:"size";s:6:"80,255";s:4:"span";s:5:"all,b";s:4:"name";s:12:"info_subject";s:4:"help";s:29:"a short subject for the entry";s:8:"readonly";s:1:"1";}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:1:{s:4:"type";s:5:"label";}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:7;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:5:"label";s:11:"Description";}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:8;a:4:{s:1:"A";a:6:{s:4:"type";s:8:"textarea";s:7:"no_lang";s:1:"1";s:4:"name";s:8:"info_des";s:4:"help";s:44:"enter a textual description of the log-entry";s:4:"span";s:15:"all,description";s:8:"readonly";s:1:"1";}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:1:{s:4:"type";s:5:"label";}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:10;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:5:"label";s:12:"customfields";}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:11;a:4:{s:1:"A";a:4:{s:4:"type";s:12:"customfields";s:4:"span";s:3:"all";s:8:"readonly";s:1:"1";s:4:"size";s:10:"@info_type";}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:12;a:4:{s:1:"A";a:3:{s:4:"type";s:8:"template";s:4:"span";s:3:"all";s:4:"name";s:26:"infolog.edit.print.project";}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:13;a:4:{s:1:"A";a:3:{s:4:"type";s:8:"template";s:4:"name";s:24:"infolog.edit.print.links";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:14;a:4:{s:1:"A";a:1:{s:4:"type";s:5:"label";}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:15;a:4:{s:1:"A";a:3:{s:4:"type";s:8:"template";s:4:"name";s:29:"infolog.edit.print.delegation";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:16;a:4:{s:1:"A";a:1:{s:4:"type";s:5:"label";}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:17;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:5:"label";s:21:"Dates, Status, Access";}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:18;a:4:{s:1:"A";a:4:{s:4:"type";s:5:"label";s:5:"label";s:9:"Startdate";s:4:"size";s:17:",,,info_startdate";s:8:"readonly";s:1:"1";}s:1:"B";a:5:{s:4:"type";s:9:"date-time";s:4:"size";s:2:",2";s:4:"name";s:14:"info_startdate";s:4:"help";s:115:"when should the ToDo or Phonecall be started, it shows up from that date in the filter open or own open (startpage)";s:8:"readonly";s:1:"1";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:5:"label";s:7:"Enddate";s:4:"size";s:15:",,,info_enddate";}s:1:"D";a:4:{s:4:"type";s:4:"date";s:4:"name";s:12:"info_enddate";s:4:"help";s:49:"til when should the ToDo or Phonecall be finished";s:8:"readonly";s:1:"1";}}i:19;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:5:"label";s:6:"Status";s:4:"size";s:14:",,,info_status";}s:1:"B";a:5:{s:4:"type";s:6:"select";s:4:"name";s:11:"info_status";s:4:"help";s:12:"@status_help";s:8:"onchange";s:183:"if (this.value==\'done\' || this.value==\'billed\') set_element(this.form,\'exec[info_percent]\',\'100\'); else if (this.value==\'not-started\') set_element(this.form,\'exec[info_percent]\',\'0\');";s:8:"readonly";s:1:"1";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:5:"label";s:9:"Completed";s:4:"size";s:15:",,,info_percent";}s:1:"D";a:5:{s:4:"type";s:14:"select-percent";s:4:"name";s:12:"info_percent";s:4:"help";s:17:"Percent completed";s:8:"onchange";s:570:"if (this.value==100 && this.form[\'exec[info_status]\'].value != \'done\' && this.form[\'exec[info_status]\'].value != \'billed\' && this.form[\'exec[info_status]\'].value != \'cancelled\') this.form[\'exec[info_status]\'].value=\'done\'; else if (this.value != 100 && this.form[\'exec[info_status]\'].value != \'cancelled\') this.form[\'exec[info_status]\'].value=this.value != 0 ? \'ongoing\' : \'not-started\'; else if (this.value==0 && this.form[\'exec[info_status]\'].value != \'cancelled\' && this.form[\'exec[info_status]\'].value != \'offer\') this.form[\'exec[info_status]\'].value=\'not-started\'; ";s:8:"readonly";s:1:"1";}}i:20;a:4:{s:1:"A";a:4:{s:4:"type";s:5:"label";s:4:"size";s:21:",,,info_datecompleted";s:5:"label";s:14:"Date completed";s:8:"readonly";s:1:"1";}s:1:"B";a:4:{s:4:"type";s:9:"date-time";s:4:"name";s:18:"info_datecompleted";s:4:"help";s:84:"Date completed (leave it empty to have it automatic set if status is done or billed)";s:8:"readonly";s:1:"1";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:5:"label";s:7:"Private";s:4:"size";s:14:",,,info_access";}s:1:"D";a:5:{s:4:"type";s:8:"checkbox";s:4:"size";s:14:"private,public";s:4:"name";s:11:"info_access";s:4:"help";s:87:"should this entry only be visible to you and people you grant privat access via the ACL";s:8:"readonly";s:1:"1";}}i:21;a:4:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:5:"Owner";}s:1:"B";a:3:{s:4:"type";s:14:"select-account";s:4:"name";s:10:"info_owner";s:8:"readonly";s:1:"1";}s:1:"C";a:2:{s:4:"type";s:5:"label";s:5:"label";s:13:"Last modified";}s:1:"D";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:5:"2,0,0";i:1;a:3:{s:4:"type";s:14:"select-account";s:4:"name";s:13:"info_modifier";s:8:"readonly";s:1:"1";}i:2;a:4:{s:4:"type";s:9:"date-time";s:4:"span";s:10:",lpadding5";s:4:"name";s:17:"info_datemodified";s:8:"readonly";s:1:"1";}}}}s:4:"rows";i:21;s:4:"cols";i:4;s:4:"size";s:4:"100%";s:7:"options";a:1:{i:0;s:4:"100%";}}}','size' => '100%','style' => '.hideFrom input { display: none; }
.link_select select { width: 250px; }
-.description textarea { width: 98%; }','modified' => '1260711082',);
+.description textarea { width: 98%; }','modified' => '1266862572',);
$templ_data[] = array('name' => 'infolog.edit.print.delegation','template' => '','lang' => '','group' => '0','version' => '1.7.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:7:{i:0;a:10:{s:1:"A";s:3:"100";s:2:"c1";s:2:"th";s:2:"c2";s:3:"row";s:2:"c3";s:3:"row";s:2:"c4";s:2:"th";s:2:"c5";s:7:"row,top";s:2:"c6";s:3:"row";s:2:"h6";s:2:",1";s:2:"h1";s:2:"10";s:2:"h4";s:2:"10";}i:1;a:2:{s:1:"A";a:3:{s:4:"span";s:3:"all";s:4:"type";s:5:"label";s:5:"label";s:7:"General";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:3:{s:4:"size";s:16:",,,info_priority";s:4:"type";s:5:"label";s:5:"label";s:8:"Priority";}s:1:"B";a:4:{s:4:"name";s:13:"info_priority";s:4:"type";s:6:"select";s:4:"help";s:31:"select a priority for this task";s:8:"readonly";s:1:"1";}}i:3;a:2:{s:1:"A";a:4:{s:4:"size";s:16:",,,info_location";s:4:"type";s:5:"label";s:5:"label";s:8:"Location";s:8:"readonly";s:1:"1";}s:1:"B";a:4:{s:4:"size";s:6:"80,255";s:4:"name";s:13:"info_location";s:4:"type";s:4:"text";s:8:"readonly";s:1:"1";}}i:4;a:2:{s:1:"A";a:3:{s:4:"span";s:3:"all";s:4:"type";s:5:"label";s:5:"label";s:10:"Delegation";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:5;a:2:{s:1:"A";a:4:{s:4:"size";s:19:",,,info_responsible";s:4:"type";s:5:"label";s:5:"label";s:11:"Responsible";s:8:"readonly";s:1:"1";}s:1:"B";a:5:{s:4:"type";s:14:"select-account";s:4:"name";s:16:"info_responsible";s:4:"size";s:7:"10,both";s:4:"help";s:66:"select a responsible user: a person you want to delegate this task";s:8:"readonly";s:1:"1";}}i:6;a:2:{s:1:"A";a:3:{s:4:"size";s:15:",,,info_confirm";s:4:"type";s:5:"label";s:5:"label";s:7:"Confirm";}s:1:"B";a:4:{s:4:"name";s:12:"info_confirm";s:4:"type";s:6:"select";s:4:"help";s:87:"do you want a confirmation of the responsible on: accepting, finishing the task or both";s:8:"readonly";s:1:"1";}}}s:4:"cols";i:2;s:4:"rows";i:6;s:4:"size";s:4:"100%";s:7:"options";a:1:{i:0;s:4:"100%";}}}','size' => '100%','style' => '','modified' => '1260707728',);
From 48886af55c6ff5da4c8dc560875b0d1e87b34423 Mon Sep 17 00:00:00 2001
From: Nathan Gray
Date: Mon, 22 Feb 2010 20:56:59 +0000
Subject: [PATCH 021/334] Blur text can affect regular searches, not just array
searches
---
etemplate/inc/class.ajax_select_widget.inc.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/etemplate/inc/class.ajax_select_widget.inc.php b/etemplate/inc/class.ajax_select_widget.inc.php
index 71dc0ba16d..c35965b2fe 100644
--- a/etemplate/inc/class.ajax_select_widget.inc.php
+++ b/etemplate/inc/class.ajax_select_widget.inc.php
@@ -254,7 +254,7 @@ class ajax_select_widget
$value_in = $extension_data['old_value'];
}
// Check for blur text left in
- if($extension_data['options']['id_field'] == self::ARRAY_KEY && $value_in['search'] == lang('Search...') ) {
+ if($value_in['search'] == lang('Search...') ) {
$value_in['search'] = '';
}
From 5e2d3f47396bacc668f16dca8563afb6ac4d1669 Mon Sep 17 00:00:00 2001
From: Nathan Gray
Date: Mon, 22 Feb 2010 21:25:00 +0000
Subject: [PATCH 022/334] Fix for lost links when copying. All links get
copied now, including the one in the header.
---
infolog/inc/class.infolog_ui.inc.php | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/infolog/inc/class.infolog_ui.inc.php b/infolog/inc/class.infolog_ui.inc.php
index e3f5c64845..09e29c6ed3 100644
--- a/infolog/inc/class.infolog_ui.inc.php
+++ b/infolog/inc/class.infolog_ui.inc.php
@@ -854,7 +854,15 @@ class infolog_ui
unset($content['info_id']);
unset ($info_id);
unset($content['info_datemodified']);
- unset($contentt['info_modifier']);
+ unset($content['info_modifier']);
+
+ // Get links to be copied
+ $content['link_to']['to_id'] = egw_link::get_links($content['link_to']['to_app'], $content['link_to']['to_id']);
+ if($content['info_link_id']) {
+ $info_link_id = $content['info_link_id'];
+ unset($content['info_link_id']);
+ }
+
$content['info_owner'] = !(int)$this->owner || !$this->bo->check_perms(EGW_ACL_ADD,0,$this->owner) ? $this->user : $this->owner;
$content['msg'] = lang('Infolog copied - the copy can now be edited');
$content['info_subject'] = lang('Copy of:').' '.$content['info_subject'];
From 4424d49c304f67fbeb28cb6f9c8b607daf3face9 Mon Sep 17 00:00:00 2001
From: Nathan Gray
Date: Mon, 22 Feb 2010 22:46:17 +0000
Subject: [PATCH 023/334] Handle case when ID is missing, happens the time
after clearing the cf search
---
etemplate/inc/class.nextmatch_widget.inc.php | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/etemplate/inc/class.nextmatch_widget.inc.php b/etemplate/inc/class.nextmatch_widget.inc.php
index ba640fb36f..ceaf1fa62a 100644
--- a/etemplate/inc/class.nextmatch_widget.inc.php
+++ b/etemplate/inc/class.nextmatch_widget.inc.php
@@ -970,7 +970,14 @@ class nextmatch_widget
}
foreach($this->cfs as $name => $field) {
if($GLOBALS['egw_info']['apps'][$field['type']]) {
- if ((string)$value_in[self::CF_PREFIX.$name] != (string)$extension_data['old_value'][self::CF_PREFIX.$name])
+ if(is_array($value_in[self::CF_PREFIX.$name])) {
+ list($old_app, $old_id) = explode(':', $extension_data['old_value'][self::CF_PREFIX.$name]);
+ if($value_in[self::CF_PREFIX.$name]['id'] != '' && $value_in[self::CF_PREFIX.$name]['id'] != $old_id) {
+ $nm_global['filter'][self::CF_PREFIX.$name] = $value_in[self::CF_PREFIX.$name]['id'];
+ }
+
+ }
+ elseif ((string)$value_in[self::CF_PREFIX.$name] != (string)$extension_data['old_value'][self::CF_PREFIX.$name])
{
$nm_global['filter'][self::CF_PREFIX.$name] = $value_in[self::CF_PREFIX.$name]['id'];
}
From 0b79a0466d018a7e1ff920e7c20d66febf12ebe0 Mon Sep 17 00:00:00 2001
From: Nathan Gray
Date: Mon, 22 Feb 2010 23:02:25 +0000
Subject: [PATCH 024/334] Make changing status for whole query work
---
timesheet/inc/class.timesheet_ui.inc.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/timesheet/inc/class.timesheet_ui.inc.php b/timesheet/inc/class.timesheet_ui.inc.php
index cf5bb95259..6889615907 100644
--- a/timesheet/inc/class.timesheet_ui.inc.php
+++ b/timesheet/inc/class.timesheet_ui.inc.php
@@ -759,7 +759,7 @@ class timesheet_ui extends timesheet_bo
else
{
if ($this->action($content['action'],$content['nm']['rows']['checked'],$content['use_all'],
- $success,$failed,$action_msg,$content['action'],$msg))
+ $success,$failed,$action_msg,'index',$msg))
{
$msg .= lang('%1 timesheets(s) %2',$success,$action_msg);
}
From de840a1fcc52721d8d0bf12f8b70085d31eaf9ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Lehrke?=
Date: Tue, 23 Feb 2010 18:18:10 +0000
Subject: [PATCH 025/334] Fix empty field issue
---
phpgwapi/inc/horde/Horde/iCalendar.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/phpgwapi/inc/horde/Horde/iCalendar.php b/phpgwapi/inc/horde/Horde/iCalendar.php
index f6e99fd9df..6c5454d473 100644
--- a/phpgwapi/inc/horde/Horde/iCalendar.php
+++ b/phpgwapi/inc/horde/Horde/iCalendar.php
@@ -1222,7 +1222,7 @@ class Horde_iCalendar {
$attr_string = $name . $params_str;
if (strlen($value) > 0) {
$attr_string .= ':' . $value;
- } elseif ($name != 'RRULE') {
+ } elseif ($name != 'RRULE' && $name != 'ATTENDEE' && $name != 'ORGANIZER') {
$attr_string .= ':';
}
if (!$this->isOldFormat()) {
From 85b6ba5ef0d130be1abce3957d6a1cb8ccb6b7af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Lehrke?=
Date: Tue, 23 Feb 2010 18:19:12 +0000
Subject: [PATCH 026/334] Cleanup issues found during backport
---
calendar/inc/class.calendar_groupdav.inc.php | 25 ++++++++++++------
calendar/inc/class.calendar_ical.inc.php | 27 +++++++++-----------
calendar/inc/class.calendar_sif.inc.php | 14 +++++-----
calendar/inc/class.calendar_so.inc.php | 9 ++++---
4 files changed, 42 insertions(+), 33 deletions(-)
diff --git a/calendar/inc/class.calendar_groupdav.inc.php b/calendar/inc/class.calendar_groupdav.inc.php
index 5883a74643..8d89eb15f3 100644
--- a/calendar/inc/class.calendar_groupdav.inc.php
+++ b/calendar/inc/class.calendar_groupdav.inc.php
@@ -98,8 +98,11 @@ class calendar_groupdav extends groupdav_handler
*/
function propfind($path,$options,&$files,$user,$id='')
{
- if ($this->debug) error_log(__METHOD__."($path,".array2string($options).",,$user,$id)");
- $starttime = microtime(true);
+ if ($this->debug)
+ {
+ error_log(__METHOD__."($path,".array2string($options).",,$user,$id)");
+ $starttime = microtime(true);
+ }
// ToDo: add parameter to only return id & etag
$cal_filters = array(
@@ -121,7 +124,11 @@ class calendar_groupdav extends groupdav_handler
{
return false;
}
- if ($this->debug > 1) error_log(__METHOD__."($path,,,$user,$id) cal_filters=".array2string($cal_filters));
+ if ($this->debug > 1)
+ {
+ error_log(__METHOD__."($path,,,$user,$id) cal_filters=".
+ array2string($cal_filters));
+ }
// check if we have to return the full calendar data or just the etag's
if (!($calendar_data = $options['props'] == 'all' && $options['root']['ns'] == groupdav::CALDAV) && is_array($options['props']))
@@ -183,7 +190,11 @@ class calendar_groupdav extends groupdav_handler
);
}
}
- if ($this->debug) error_log(__METHOD__."($path) took ".(microtime(true) - $starttime).' to return '.count($files['files']).' items');
+ if ($this->debug)
+ {
+ error_log(__METHOD__."($path) took ".(microtime(true) - $starttime).
+ ' to return '.count($files['files']).' items');
+ }
return true;
}
@@ -284,11 +295,9 @@ class calendar_groupdav extends groupdav_handler
{
foreach($options['other'] as $option)
{
-
if ($option['name'] == 'href')
{
$parts = explode('/',$option['data']);
-
if (is_numeric($id = basename(array_pop($parts),'.ics'))) $ids[] = $id;
}
}
@@ -424,13 +433,13 @@ class calendar_groupdav extends groupdav_handler
*/
function put(&$options,$id,$user=null)
{
- if($this->debug) error_log(__METHOD__."($id, $user)".print_r($options,true));
+ if ($this->debug) error_log(__METHOD__."($id, $user)".print_r($options,true));
$return_no_access=true; // as handled by importVCal anyway and allows it to set the status for participants
$event = $this->_common_get_put_delete('PUT',$options,$id,$return_no_access);
if (!is_null($event) && !is_array($event))
{
- if($this->debug) error_log(__METHOD__.print_r($event,true).function_backtrace());
+ if ($this->debug) error_log(__METHOD__.print_r($event,true).function_backtrace());
return $event;
}
$handler = $this->_get_handler();
diff --git a/calendar/inc/class.calendar_ical.inc.php b/calendar/inc/class.calendar_ical.inc.php
index 04834cc128..3c9f0b1948 100644
--- a/calendar/inc/class.calendar_ical.inc.php
+++ b/calendar/inc/class.calendar_ical.inc.php
@@ -196,6 +196,7 @@ class calendar_ical extends calendar_boupdate
'UID' => 'uid',
'RECURRENCE-ID' => 'recurrence',
'SEQUENCE' => 'etag',
+ 'STATUS' => 'status',
);
if (!is_array($this->supportedFields)) $this->setSupportedFields();
@@ -218,7 +219,7 @@ class calendar_ical extends calendar_boupdate
{
$mailtoOrganizer = false;
$organizerCN = false;
- $recurrence = $recur_date;
+ $recurrence = $this->date2usertime($recur_date);
$tzid = null;
if (!is_array($event)
@@ -622,6 +623,10 @@ class calendar_ical extends calendar_boupdate
}
break;
+ case 'STATUS':
+ $attributes['STATUS'] = 'CONFIRMED';
+ break;
+
case 'CATEGORIES':
if ($event['category'] && ($values['CATEGORIES'] = $this->get_categories($event['category'])))
{
@@ -641,12 +646,12 @@ class calendar_ical extends calendar_boupdate
{
$icalFieldName = 'X-RECURRENCE-ID';
}
- if ($recurrence)
+ if ($recur_date)
{
// We handle a pseudo exception
if (isset($event['whole_day']))
{
- $time = new egw_time($recurrence,egw_time::$server_timezone);
+ $time = new egw_time($recur_date,egw_time::$server_timezone);
$time->setTimezone(self::$tz_cache[$event['tzid']]);
$arr = egw_time::to($time,'array');
$vevent->setAttribute($icalFieldName, array(
@@ -658,7 +663,7 @@ class calendar_ical extends calendar_boupdate
}
else
{
- $attributes[$icalFieldName] = self::getDateTime($recurrence,$tzid,$parameters[$icalFieldName]);
+ $attributes[$icalFieldName] = self::getDateTime($recur_date,$tzid,$parameters[$icalFieldName]);
}
}
elseif ($event['recurrence'] && $event['reference'])
@@ -734,7 +739,6 @@ class calendar_ical extends calendar_boupdate
{
$attributes[$icalFieldName] = $value;
}
- break;
}
}
@@ -1089,8 +1093,8 @@ class calendar_ical extends calendar_boupdate
// If this is an updated meeting, and the client doesn't support
// participants OR the event no longer contains participants, add them back
- $event['participants'] = $event_info['stored_event']['participants'];
- $event['participant_types'] = $event_info['stored_event']['participant_types'];
+ unset($event['participants']);
+ unset($event['participant_types']);
}
else
{
@@ -1748,6 +1752,7 @@ class calendar_ical extends calendar_boupdate
$defaultFields['basic'] = $defaultFields['minimal'] + array(
'recur_exception' => 'recur_exception',
'priority' => 'priority',
+ 'status' => 'status',
);
$defaultFields['nexthaus'] = $defaultFields['basic'] + array(
@@ -2662,14 +2667,6 @@ class calendar_ical extends calendar_boupdate
function search($_vcalData, $contentID=null, $relax=false)
{
- if (is_null($contentID))
- {
- $eventId = -1;
- }
- else
- {
- $eventId = $contentID;
- }
if (($events = $this->icaltoegw($_vcalData)))
{
// this function only supports searching a single event
diff --git a/calendar/inc/class.calendar_sif.inc.php b/calendar/inc/class.calendar_sif.inc.php
index 6551ebd2f9..f75ffd2a6e 100644
--- a/calendar/inc/class.calendar_sif.inc.php
+++ b/calendar/inc/class.calendar_sif.inc.php
@@ -312,10 +312,7 @@ class calendar_sif extends calendar_boupdate
if ($this->event['recur_noenddate'] == 0)
{
$recur_enddate = $this->vCalendar->_parseDateTime($this->event['recur_enddate']);
- $finalEvent['recur_enddate'] = mktime(
- date('H', 23),
- date('i', 59),
- date('s', 59),
+ $finalEvent['recur_enddate'] = mktime(0, 0, 0,
date('m', $recur_enddate),
date('d', $recur_enddate),
date('Y', $recur_enddate));
@@ -480,6 +477,11 @@ class calendar_sif extends calendar_boupdate
// overwrite with server data for merge
foreach ($event_info['stored_event'] as $key => $value)
{
+ if (in_array($key, array('participants', 'participant_types')))
+ {
+ unset($event[$key]);
+ continue;
+ }
if (!empty($value)) $event[$key] = $value;
}
}
@@ -487,8 +489,8 @@ class calendar_sif extends calendar_boupdate
{
// not merge
// SIF clients do not support participants => add them back
- $event['participants'] = $event_info['stored_event']['participants'];
- $event['participant_types'] = $event_info['stored_event']['participant_types'];
+ unset($event['participants']);
+ unset($event['participant_types']);
if ($event['whole_day'] && $event['tzid'] != $event_info['stored_event']['tzid'])
{
if (!isset(self::$tz_cache[$event_info['stored_event']['tzid']]))
diff --git a/calendar/inc/class.calendar_so.inc.php b/calendar/inc/class.calendar_so.inc.php
index f5cf124b7b..001aed31d3 100644
--- a/calendar/inc/class.calendar_so.inc.php
+++ b/calendar/inc/class.calendar_so.inc.php
@@ -1491,16 +1491,14 @@ ORDER BY cal_user_type, cal_usre_id
* get stati of all recurrences of an event for a specific participant
*
* @param int $cal_id
- * @param int $uid participant uid
+ * @param int $uid=null participant uid; if == null return only the recur dates
* @param int $start=0 if != 0: startdate of the search/list (servertime)
* @param int $end=0 if != 0: enddate of the search/list (servertime)
*
* @return array recur_date => status pairs (index 0 => main status)
*/
- function get_recurrences($cal_id, $uid, $start=0, $end=0)
+ function get_recurrences($cal_id, $uid=null, $start=0, $end=0)
{
- $user_type = $user_id = null;
- self::split_user($uid, $user_type, $user_id);
$participant_status = array();
$where = array('cal_id' => $cal_id);
if ($start != 0 && $end == 0) $where[] = '(cal_recur_date = 0 OR cal_recur_date >= ' . (int)$start . ')';
@@ -1515,6 +1513,9 @@ ORDER BY cal_user_type, cal_usre_id
// inititalize the array
$participant_status[$row['cal_recur_date']] = null;
}
+ if (is_null($uid)) return $participant_status;
+ $user_type = $user_id = null;
+ self::split_user($uid, $user_type, $user_id);
$where = array(
'cal_id' => $cal_id,
'cal_user_type' => $user_type ? $user_type : 'u',
From b2b8b353832f6b80397ca4a958ee974b142af210 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Lehrke?=
Date: Wed, 24 Feb 2010 15:05:00 +0000
Subject: [PATCH 027/334] Fix various recurring event issues
---
calendar/inc/class.calendar_ical.inc.php | 135 +++++++++++---------
calendar/inc/class.calendar_sif.inc.php | 3 +-
calendar/inc/class.calendar_uiforms.inc.php | 17 +--
3 files changed, 83 insertions(+), 72 deletions(-)
diff --git a/calendar/inc/class.calendar_ical.inc.php b/calendar/inc/class.calendar_ical.inc.php
index 3c9f0b1948..0d30209d9c 100644
--- a/calendar/inc/class.calendar_ical.inc.php
+++ b/calendar/inc/class.calendar_ical.inc.php
@@ -211,6 +211,7 @@ class calendar_ical extends calendar_boupdate
strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang']));
$vcal->setAttribute('VERSION', $version);
$vcal->setAttribute('METHOD', $method);
+ $events_exported = false;
if (!is_array($events)) $events = array($events);
@@ -893,9 +894,10 @@ class calendar_ical extends calendar_boupdate
}
}
$vcal->addComponent($vevent);
+ $events_exported = true;
}
- $retval = $vcal->exportvCalendar();
+ $retval = $events_exported ? $vcal->exportvCalendar() : false;
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ .
@@ -1070,7 +1072,7 @@ class calendar_ical extends calendar_boupdate
if (!isset($event['participants'][$uid]))
{
// Add it back in
- $event['participants'][$uid] = $event['participant_types']['r'][substr($uid,1)] = $status;
+ $event['participants'][$uid] = $status;
}
}
break;
@@ -1083,7 +1085,14 @@ class calendar_ical extends calendar_boupdate
else
{
// no merge
- if (!isset($this->supportedFields['participants']) || !count($event['participants']))
+ if(!isset($this->supportedFields['category']))
+ {
+ $event['category'] = $event_info['stored_event']['category'];
+ }
+ if (!isset($this->supportedFields['participants'])
+ || !$event['participants']
+ || !is_array($event['participants'])
+ || !count($event['participants']))
{
if ($this->log)
{
@@ -1094,7 +1103,6 @@ class calendar_ical extends calendar_boupdate
// If this is an updated meeting, and the client doesn't support
// participants OR the event no longer contains participants, add them back
unset($event['participants']);
- unset($event['participant_types']);
}
else
{
@@ -1119,20 +1127,19 @@ class calendar_ical extends calendar_boupdate
}
}
}
- }
-
- foreach ($event_info['stored_event']['participants'] as $uid => $status)
- {
- // Is it a resource and no longer present in the event?
- if ($uid[0] == 'r' && !isset($event['participants'][$uid]))
+ foreach ($event_info['stored_event']['participants'] as $uid => $status)
{
- if ($this->log)
+ // Is it a resource and no longer present in the event?
+ if ($uid[0] == 'r' && !isset($event['participants'][$uid]))
{
- error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
- "() Restore resource $uid to status $status\n",3,$this->logfile);
+ if ($this->log)
+ {
+ error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
+ "() Restore resource $uid to status $status\n",3,$this->logfile);
+ }
+ // Add it back in
+ $event['participants'][$uid] = $status;
}
- // Add it back in
- $event['participants'][$uid] = $event['participant_types']['r'][substr($uid,1)] = $status;
}
}
@@ -1188,7 +1195,9 @@ class calendar_ical extends calendar_boupdate
$event['owner'] = $this->user;
}
- if (!is_array($event['participants']) || !count($event['participants']))
+ if (!$event['participants']
+ || !is_array($event['participants'])
+ || !count($event['participants']))
{
$status = $event['owner'] == $this->user ? 'A' : 'U';
$status = calendar_so::combine_status($status, 1, 'CHAIR');
@@ -1198,7 +1207,7 @@ class calendar_ical extends calendar_boupdate
{
foreach ($event['participants'] as $uid => $status)
{
- // Is it a resource and no longer present in the event?
+ // if the client did not give us a proper status => set default
if ($status[0] == 'X')
{
if ($uid == $event['owner'])
@@ -1499,46 +1508,49 @@ class calendar_ical extends calendar_boupdate
$event_info['stored_event'] = $this->read($updated_id, 0, false, 'server');
}
- // update status depending on the given event type
- switch ($event_info['type'])
+ if (isset($event['participants']))
{
- case 'SINGLE':
- case 'SERIES-MASTER':
- case 'SERIES-EXCEPTION':
- case 'SERIES-EXCEPTION-PROPAGATE':
- if (is_array($event_info['stored_event'])) // status update requires a stored event
- {
- if ($event_info['acl_edit'])
+ // update status depending on the given event type
+ switch ($event_info['type'])
+ {
+ case 'SINGLE':
+ case 'SERIES-MASTER':
+ case 'SERIES-EXCEPTION':
+ case 'SERIES-EXCEPTION-PROPAGATE':
+ if (is_array($event_info['stored_event'])) // status update requires a stored event
{
- // update all participants if we have the right to do that
- $this->update_status($event, $event_info['stored_event']);
+ if ($event_info['acl_edit'])
+ {
+ // update all participants if we have the right to do that
+ $this->update_status($event, $event_info['stored_event']);
+ }
+ elseif (isset($event['participants'][$this->user]) || isset($event_info['stored_event']['participants'][$this->user]))
+ {
+ // update the users status only
+ $this->set_status($event_info['stored_event']['id'], $this->user,
+ ($event['participants'][$this->user] ? $event['participants'][$this->user] : 'R'), 0, true);
+ }
}
- elseif (isset($event['participants'][$this->user]) || isset($event_info['stored_event']['participants'][$this->user]))
- {
- // update the users status only
- $this->set_status($event_info['stored_event']['id'], $this->user,
- ($event['participants'][$this->user] ? $event['participants'][$this->user] : 'R'), 0, true);
- }
- }
- break;
+ break;
- case 'SERIES-PSEUDO-EXCEPTION':
- if (is_array($event_info['master_event'])) // status update requires a stored master event
- {
- $recurrence = $this->date2usertime($event['recurrence']);
- if ($event_info['acl_edit'])
+ case 'SERIES-PSEUDO-EXCEPTION':
+ if (is_array($event_info['master_event'])) // status update requires a stored master event
{
- // update all participants if we have the right to do that
- $this->update_status($event, $event_info['stored_event'], $recurrence);
+ $recurrence = $this->date2usertime($event['recurrence']);
+ if ($event_info['acl_edit'])
+ {
+ // update all participants if we have the right to do that
+ $this->update_status($event, $event_info['stored_event'], $recurrence);
+ }
+ elseif (isset($event['participants'][$this->user]) || isset($event_info['master_event']['participants'][$this->user]))
+ {
+ // update the users status only
+ $this->set_status($event_info['master_event']['id'], $this->user,
+ ($event['participants'][$this->user] ? $event['participants'][$this->user] : 'R'), $recurrence, true);
+ }
}
- elseif (isset($event['participants'][$this->user]) || isset($event_info['master_event']['participants'][$this->user]))
- {
- // update the users status only
- $this->set_status($event_info['master_event']['id'], $this->user,
- ($event['participants'][$this->user] ? $event['participants'][$this->user] : 'R'), $recurrence, true);
- }
- }
- break;
+ break;
+ }
}
// choose which id to return to the client
@@ -1864,6 +1876,7 @@ class calendar_ical extends calendar_boupdate
case 'd750i':
case 'p910i':
case 'g705i':
+ case 'w890i':
$this->supportedFields = $defaultFields['basic'];
break;
default:
@@ -2491,7 +2504,7 @@ class calendar_ical extends calendar_boupdate
{
//Horde::logMessage("vevent2egw: set status to " . $status,
// __FILE__, __LINE__, PEAR_LOG_DEBUG);
- $event['participants'][$this->user] =
+ $vcardData['participants'][$this->user] =
calendar_so::combine_status($status);
}
$status = 'U'; // keep the group
@@ -2532,12 +2545,12 @@ class calendar_ical extends calendar_boupdate
{
$attributes['params']['ROLE'] = 'CHAIR';
}
- if (!isset($event['participants'][$uid]) ||
- $event['participants'][$uid][0] != 'A')
+ if (!isset($vcardData['participants'][$uid]) ||
+ $vcardData['participants'][$uid][0] != 'A')
{
// for multiple entries the ACCEPT wins
// add quantity and role
- $event['participants'][$uid] =
+ $vcardData['participants'][$uid] =
calendar_so::combine_status($status,
$attributes['params']['X-EGROUPWARE-QUANTITY'],
$attributes['params']['ROLE']);
@@ -2545,11 +2558,11 @@ class calendar_ical extends calendar_boupdate
break;
case 'ORGANIZER':
- if (isset($event['participants'][$uid]))
+ if (isset($vcardData['participants'][$uid]))
{
- $status = $event['participants'][$uid];
+ $status = $vcardData['participants'][$uid];
calendar_so::split_status($status, $quantity, $role);
- $event['participants'][$uid] =
+ $vcardData['participants'][$uid] =
calendar_so::combine_status($status, $quantity, 'CHAIR');
}
if (is_numeric($uid) && ($uid == $this->calendarOwner || !$this->calendarOwner))
@@ -2561,10 +2574,10 @@ class calendar_ical extends calendar_boupdate
{
// we must insert a CHAIR participant to keep the ORGANIZER
$event['owner'] = $this->user;
- if (!isset($event['participants'][$uid]))
+ if (!isset($vcardData['participants'][$uid]))
{
// save the ORGANIZER as event CHAIR
- $event['participants'][$uid] =
+ $vcardData['participants'][$uid] =
calendar_so::combine_status('U', 1, 'CHAIR');
}
}
@@ -2781,6 +2794,8 @@ class calendar_ical extends calendar_boupdate
*/
function update_status($new_event, $old_event , $recur_date=0)
{
+ if (!isset($new_event['participants'])) return;
+
// check the old list against the new list
foreach ($old_event['participants'] as $userid => $status)
{
diff --git a/calendar/inc/class.calendar_sif.inc.php b/calendar/inc/class.calendar_sif.inc.php
index f75ffd2a6e..12f45b2b7a 100644
--- a/calendar/inc/class.calendar_sif.inc.php
+++ b/calendar/inc/class.calendar_sif.inc.php
@@ -477,7 +477,7 @@ class calendar_sif extends calendar_boupdate
// overwrite with server data for merge
foreach ($event_info['stored_event'] as $key => $value)
{
- if (in_array($key, array('participants', 'participant_types')))
+ if ($key == 'participants')
{
unset($event[$key]);
continue;
@@ -490,7 +490,6 @@ class calendar_sif extends calendar_boupdate
// not merge
// SIF clients do not support participants => add them back
unset($event['participants']);
- unset($event['participant_types']);
if ($event['whole_day'] && $event['tzid'] != $event_info['stored_event']['tzid'])
{
if (!isset(self::$tz_cache[$event_info['stored_event']['tzid']]))
diff --git a/calendar/inc/class.calendar_uiforms.inc.php b/calendar/inc/class.calendar_uiforms.inc.php
index 3514e2204e..3086131594 100644
--- a/calendar/inc/class.calendar_uiforms.inc.php
+++ b/calendar/inc/class.calendar_uiforms.inc.php
@@ -238,7 +238,7 @@ class calendar_uiforms extends calendar_ui
$event['end']['hour'] = 23; $event['end']['minute'] = $event['end']['second'] = 59; unset($event['end']['raw']);
$event['end'] = $this->bo->date2ts($event['end']);
}
- // some checks for recurances, if you give a date, make it a weekly repeating event and visa versa
+ // some checks for recurrences, if you give a date, make it a weekly repeating event and visa versa
if ($event['recur_type'] == MCAL_RECUR_NONE && $event['recur_data']) $event['recur_type'] = MCAL_RECUR_WEEKLY;
if ($event['recur_type'] == MCAL_RECUR_WEEKLY && !$event['recur_data'])
{
@@ -833,14 +833,11 @@ class calendar_uiforms extends calendar_ui
// check if we should create an exception
if ($_GET['exception'])
{
- // exception: preserv participants of this event and merge it with the 0-recurrence
- $participants = array('participants' => $event['participants'],'participant_types' => $event['participant_types']);
- $event = array_merge($this->bo->read($cal_id,0,true),$participants);
$msg = $this->_create_exception($event,$preserv);
}
else
{
- $event = $this->bo->read($cal_id,0,true); // read the 0-recurrence
+ $event = $this->bo->read($cal_id,0,true);
}
}
}
@@ -1077,12 +1074,12 @@ class calendar_uiforms extends calendar_ui
$GLOBALS['egw']->js->set_onload("set_style_by_class('table','end_hide','display','".($content['duration'] && isset($sel_options['duration'][$content['duration']]) ? 'none' : 'block')."');");
$readonlys['recur_exception'] = !count($content['recur_exception']); // otherwise we get a delete button
-
+
if ($event['recur_type'] != MCAL_RECUR_NONE)
{
$onclick =& $etpl->get_cell_attribute('button[delete]','onclick');
$onclick = str_replace('Delete this event','Delete this series of recuring events',$onclick);
-
+
// some fundamental values of an existing series should not be changed by the user
$readonlys['start'] = $readonlys['whole_day'] = true;
$readonlys['recur_type'] = $readonlys['recur_data'] = true;
@@ -1746,7 +1743,7 @@ class calendar_uiforms extends calendar_ui
'owner' => 'select-account',
'cat_id' => 'select-cat',
'non_blocking' => array(''=>lang('No'), 1=>lang('Yes')),
-
+
'start' => 'date-time',
'end' => 'date-time',
@@ -1770,11 +1767,11 @@ class calendar_uiforms extends calendar_ui
if($content['recur_type'] || $content['recurrence']) {
$content['history']['filter'] = array(
'(history_status NOT LIKE \'participants%\' OR (history_status LIKE \'participants%\' AND (
- history_new_value LIKE \'%' . bo_tracking::ONE2N_SEPERATOR . $content['recurrence'] . '\' OR
+ history_new_value LIKE \'%' . bo_tracking::ONE2N_SEPERATOR . $content['recurrence'] . '\' OR
history_old_value LIKE \'%' . bo_tracking::ONE2N_SEPERATOR . $content['recurrence'] . '\')))'
);
}
-
+
// Translate labels
$tracking = new calendar_tracking();
foreach($tracking->field2label as $field => $label) {
From c9ab7e557b85049f3c0147fde8f641fd9860e070 Mon Sep 17 00:00:00 2001
From: Klaus Leithoff
Date: Thu, 25 Feb 2010 13:42:27 +0000
Subject: [PATCH 028/334] fixing issue: failed add to organisation from
org-view, when colon in org_unit/org_location/organisation
---
addressbook/inc/class.addressbook_bo.inc.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addressbook/inc/class.addressbook_bo.inc.php b/addressbook/inc/class.addressbook_bo.inc.php
index 7f01d79a53..f77ad5561e 100755
--- a/addressbook/inc/class.addressbook_bo.inc.php
+++ b/addressbook/inc/class.addressbook_bo.inc.php
@@ -878,7 +878,7 @@ class addressbook_bo extends addressbook_so
$org = array();
foreach(explode('|||',$org_id) as $part)
{
- list($name,$value) = explode(':',$part);
+ list($name,$value) = explode(':',$part,2);
$org[$name] = $value;
}
$csvs = array('cat_id'); // fields with comma-separated-values
From 8211aef3ff11121ab0293e1625ec35cdbd868331 Mon Sep 17 00:00:00 2001
From: Christian Binder
Date: Thu, 25 Feb 2010 17:05:24 +0000
Subject: [PATCH 029/334] fixed wrong series event end times for whole day
events when events occur or span over a daylight saving date, fixed typos
---
calendar/inc/class.calendar_bo.inc.php | 29 ++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/calendar/inc/class.calendar_bo.inc.php b/calendar/inc/class.calendar_bo.inc.php
index dfb3111216..62af9b9b3f 100644
--- a/calendar/inc/class.calendar_bo.inc.php
+++ b/calendar/inc/class.calendar_bo.inc.php
@@ -853,9 +853,30 @@ class calendar_bo
//echo "
".$time." --> ignored as $ts < $start-$event_length
\n";
continue; // to early or original event (returned by interator too)
}
- //echo "
".$time." --> adding recurrence
\n";
+
+ $ts_end = $ts + $event_length;
+
+ // adjust ts_end for whole day events in case it does not fit due to
+ // spans over summer/wintertime adjusted days
+ if($event['whole_day'] && ($arr_end = $this->date2array($ts_end)) &&
+ !($arr_end['hour'] == 23 && $arr_end['minute'] == 59 && $arr_end['second'] == 59))
+ {
+ $arr_end['hour'] = 23;
+ $arr_end['minute'] = 59;
+ $arr_end['second'] = 59;
+ $ts_end_guess = $this->date2ts($arr_end);
+ if($ts_end_guess - $ts_end > DAY_s/2)
+ {
+ $ts_end = $ts_end_guess - DAY_s; // $ts_end_guess was one day too far in the future
+ }
+ else
+ {
+ $ts_end = $ts_end_guess; // $ts_end_guess was ok
+ }
+ }
+
$event['start'] = $ts;
- $event['end'] = $ts + $event_length;
+ $event['end'] = $ts_end;
$events[] = $event;
}
if ($this->debug && ((int) $this->debug > 2 || $this->debug == 'set_recurrences' || $this->debug == 'check_move_horizont' || $this->debug == 'insert_all_recurrences'))
@@ -1037,7 +1058,7 @@ class calendar_bo
}
/**
- * Converts several date-types to a timestamp and optionaly converts user- to server-time
+ * Converts several date-types to a timestamp and optionally converts user- to server-time
*
* @param mixed $date date to convert, should be one of the following types
* string (!) in form YYYYMMDD or iso8601 YYYY-MM-DDThh:mm:ss or YYYYMMDDThhmmss
@@ -1051,7 +1072,7 @@ class calendar_bo
}
/**
- * Converts a date to an array and optionaly converts server- to user-time
+ * Converts a date to an array and optionally converts server- to user-time
*
* @param mixed $date date to convert
* @param boolean $server2user_time conversation between user- and server-time default False == Off
From 731abfd2a3836561ae8e6c4c03d32a359ae9cc5b Mon Sep 17 00:00:00 2001
From: Nathan Gray
Date: Thu, 25 Feb 2010 23:13:18 +0000
Subject: [PATCH 030/334] Some more work toward completion: - Wizard now works
to define input definitions; you can define the mapping, translations and
conditions using the UI. - Added ability to schedule imports / export using
async services
Still a lot of work to be done...
---
importexport/inc/class.bodefinitions.inc.php | 11 ++
.../inc/class.iface_import_plugin.inc.php | 11 ++
...ass.import_export_helper_functions.inc.php | 5 +-
...rtexport_admin_prefs_sidebox_hooks.inc.php | 5 +-
importexport/inc/class.uidefinitions.inc.php | 33 +++--
importexport/inc/class.uiexport.inc.php | 123 ++++++++++++++----
importexport/js/export_dialog.js | 11 +-
importexport/setup/etemplates.inc.php | 28 ++--
8 files changed, 171 insertions(+), 56 deletions(-)
diff --git a/importexport/inc/class.bodefinitions.inc.php b/importexport/inc/class.bodefinitions.inc.php
index 77221d0200..d37dbbf04a 100644
--- a/importexport/inc/class.bodefinitions.inc.php
+++ b/importexport/inc/class.bodefinitions.inc.php
@@ -70,6 +70,17 @@ class bodefinitions {
}
}
+ /**
+ * Save a definition
+ *
+ * @param definition $definition
+ */
+ public function save(Array $data) {
+ $definition = new definition();
+ $definition->set_record($data);
+ $definition->save($data['definition_id']);
+ }
+
/**
* checkes if user if permitted to access given definition
*
diff --git a/importexport/inc/class.iface_import_plugin.inc.php b/importexport/inc/class.iface_import_plugin.inc.php
index a0744129cc..a168af8bea 100644
--- a/importexport/inc/class.iface_import_plugin.inc.php
+++ b/importexport/inc/class.iface_import_plugin.inc.php
@@ -31,6 +31,7 @@ interface iface_import_plugin {
*
* @param stram $_stram
* @param definition $_definition
+ * @return int number of successful imports
*/
public function import( $_stream, definition $_definition );
@@ -76,5 +77,15 @@ interface iface_import_plugin {
*/
public function get_selectors_etpl();
+ /**
+ * Returns errors that were encountered during importing
+ * Maximum of one error message per record, but you can concatenate them if you need to
+ *
+ * @return Array (
+ * record_# => error message
+ * )
+ */
+ public function get_errors();
+
} // end of iface_export_plugin
?>
diff --git a/importexport/inc/class.import_export_helper_functions.inc.php b/importexport/inc/class.import_export_helper_functions.inc.php
index b2cfe66684..4de42606bf 100755
--- a/importexport/inc/class.import_export_helper_functions.inc.php
+++ b/importexport/inc/class.import_export_helper_functions.inc.php
@@ -184,7 +184,7 @@ class import_export_helper_functions {
$CntlPre = '|TC{'; // Filter all cntl-chars \x01-\x1f and trim
$CntlnCLPre = '|TCnCL{'; // Like |C{ but allowes CR and LF
$INE = '|INE{'; // Only insert if stuff in ^^ is not empty
-
+
foreach ( $_conversion as $idx => $conversion_string ) {
if ( empty( $conversion_string ) ) continue;
@@ -221,7 +221,7 @@ class import_export_helper_functions {
}
// clean each field
$val = preg_replace_callback("/(\|T\{|\|TC\{|\|TCnCL\{|\|INE\{)(.*)\}/", array( self, 'strclean'), $val );
-
+
$_record[$idx] = $val;
}
return $_record;
@@ -249,7 +249,6 @@ class import_export_helper_functions {
}
private static function strclean( $_matches ) {
- //print_r($_matches);
switch( $_matches[1] ) {
case '|T{' : return trim( $_matches[2] );
case '|TC{' : return trim( preg_replace( '/[\x01-\x1F]+/', '', $_matches[2] ) );
diff --git a/importexport/inc/class.importexport_admin_prefs_sidebox_hooks.inc.php b/importexport/inc/class.importexport_admin_prefs_sidebox_hooks.inc.php
index ea5f1b35d9..7e5961a235 100644
--- a/importexport/inc/class.importexport_admin_prefs_sidebox_hooks.inc.php
+++ b/importexport/inc/class.importexport_admin_prefs_sidebox_hooks.inc.php
@@ -62,6 +62,9 @@ class importexport_admin_prefs_sidebox_hooks
'Define {im|ex}ports' => $GLOBALS['egw']->link('/index.php',array(
'menuaction' => 'importexport.uidefinitions.index',
)),
+ 'Schedule' => $GLOBALS['egw']->link('/index.php', array(
+ 'menuaction' => 'importexport.importexport_schedule_ui.index'
+ )),
);
if ($location == 'admin')
{
@@ -114,4 +117,4 @@ class importexport_admin_prefs_sidebox_hooks
$GLOBALS['egw']->preferences->save_repository(False,'default');
}
}
-}
\ No newline at end of file
+}
diff --git a/importexport/inc/class.uidefinitions.inc.php b/importexport/inc/class.uidefinitions.inc.php
index a6c648a875..14eacbc923 100644
--- a/importexport/inc/class.uidefinitions.inc.php
+++ b/importexport/inc/class.uidefinitions.inc.php
@@ -19,7 +19,7 @@ require_once('class.bodefinitions.inc.php');
*/
class uidefinitions
{
- const _debug = true;
+ const _debug = false;
const _appname = 'importexport';
@@ -64,12 +64,12 @@ class uidefinitions
$this->steps = array(
'wizzard_step10' => lang('Choose an application'),
'wizzard_step20' => lang('Choose a plugin'),
- 'wizzard_step80' => lang('Which useres are allowed for this definition'),
+ 'wizzard_step80' => lang('Which users are allowed to use this definition'),
'wizzard_step90' => lang('Choose a name for this definition'),
'wizzard_finish' => '',
);
- //register plugins (depricated)
- //$this->plugins = bodefinitions::plugins();
+ //register plugins
+ $this->plugins = import_export_helper_functions::get_plugins();
}
/**
@@ -134,7 +134,7 @@ class uidefinitions
}
$definition = array('name' => $_definition);
$bodefinitions = new bodefinitions();
- $bodefinitions->read($definition);
+ $definition = $bodefinitions->read($definition);
$definition['edit'] = true;
$this->wizzard($definition);
}
@@ -160,8 +160,9 @@ class uidefinitions
if($content['plugin'] && $content['application'])
{
// we need to deal with the wizzard object if exists
- if (file_exists(EGW_SERVER_ROOT . '/'. $content['application'].'/inc/class.wizzard_'. $content['plugin'].'.inc.php'))
+ if (file_exists(EGW_SERVER_ROOT . '/'. $content['application'].'/importexport/class.wizzard_'. $content['plugin'].'.inc.php'))
{
+ require_once(EGW_SERVER_ROOT . '/'. $content['application'].'/importexport/class.wizzard_'. $content['plugin'].'.inc.php');
$wizzard_plugin = 'wizzard_'.$content['plugin'];
}
else
@@ -169,7 +170,10 @@ class uidefinitions
$wizzard_plugin = $content['plugin'];
}
$this->plugin = is_object($GLOBALS['egw']->$wizzard_plugin) ? $GLOBALS['egw']->$wizzard_plugin : new $wizzard_plugin;
- if(!is_object($GLOBALS['egw']->uidefinitions)) $GLOBALS['egw']->uidefinitions =& $this;
+
+ // Global object needs to be the same, or references to plugin don't work
+ if(!is_object($GLOBALS['egw']->uidefinitions) || $GLOBALS['egw']->uidefinitions !== $this)
+ $GLOBALS['egw']->uidefinitions =& $this;
}
// deal with buttons even if we are not on ajax
if(isset($content['button']) && array_search('pressed',$content['button']) === false && count($content['button']) == 1)
@@ -273,7 +277,7 @@ class uidefinitions
$plugin_definition = $this->plugins[$content['application']][$content['plugin']]['definition'];
if($plugin_definition) $this->plugin = new $plugin_definition;
}*/
- if(is_object($this->plugin))
+ if(is_object($this->plugin) && is_array($this->plugin->steps))
{
$steps = array_merge($this->steps,$this->plugin->steps);
$steps = array_flip($steps); asort($steps); $steps = array_flip($steps);
@@ -331,7 +335,7 @@ class uidefinitions
switch (array_search('pressed', $content['button']))
{
case 'next':
- $content['type'] = $this->plugin->plugin_info['type'];
+ $content['type'] = $this->plugin instanceof iface_import_plugin ? 'import' : 'export';
return $this->get_step($content['step'],1);
case 'previous' :
unset ($content['plugin']);
@@ -347,7 +351,11 @@ class uidefinitions
else
{
$content['msg'] = $this->steps['wizzard_step20'];
- foreach ($this->plugins[$content['application']] as $plugin => $info) $sel_options['plugin'][$plugin] = $info['name'];
+ foreach ($this->plugins[$content['application']] as $type => $plugins) {
+ foreach($plugins as $plugin => $name) {
+ $sel_options['plugin'][$plugin] = $name;
+ }
+ }
$content['step'] = 'wizzard_step20';
$preserv = $content;
unset ($preserv['button']);
@@ -427,6 +435,11 @@ class uidefinitions
function wizzard_finish(&$content)
{
if(self::_debug) error_log('importexport.uidefinitions::wizzard_finish->$content '.print_r($content,true));
+ // Take out some UI leavings
+ unset($content['msg']);
+ unset($content['step']);
+ unset($content['button']);
+
$bodefinitions = new bodefinitions();
$bodefinitions->save($content);
// This message is displayed if browser cant close window
diff --git a/importexport/inc/class.uiexport.inc.php b/importexport/inc/class.uiexport.inc.php
index 211e6a46c1..87cbbd68c8 100644
--- a/importexport/inc/class.uiexport.inc.php
+++ b/importexport/inc/class.uiexport.inc.php
@@ -57,7 +57,8 @@ class uiexport {
if(empty($_content)) {
$et = new etemplate(self::_appname. '.export_dialog');
$_appname = $_GET['appname'];
- $_definition =$_GET['definition'] = 'expert';
+ //$_definition = $_GET['definition'] = 'expert';
+ $_definition = $_GET['definition'];
$_plugin = $_GET['plugin']; // NOTE: definition _must_ be 'expert' if for plugin to be used!
$_selection = $_GET['selection'];
@@ -67,6 +68,7 @@ class uiexport {
$content['appname'] = $_appname;
$preserv['appname'] = $_appname;
$readonlys['appname'] = true;
+ $this->js->set_onload("export_dialog.appname = '$_appname';");
$this->js->set_onload("set_style_by_class('tr','select_appname','display','none');");
// fill definitions
@@ -84,8 +86,9 @@ class uiexport {
}
unset($definitions);
$sel_options['definition']['expert'] = lang('Expert options');
+
- if(isset($_definition) && array_key_exists($_definition,$sel_options)) {
+ if(isset($_definition) && array_key_exists($_definition,$sel_options['definition'])) {
$content['definition'] = $_definition;
}
else {
@@ -98,16 +101,17 @@ class uiexport {
$sel_options['plugin'] = $this->export_plugins[$_appname]['export'];
// show definitions or plugins in ui?
- if($content['defintion'] == 'expert') {
+ if($content['definition'] == 'expert') {
if(isset($_plugin) && array_key_exists($_plugin,$sel_options['plugin'])) {
$content['plugin'] = $_plugin;
$selected_plugin = $_plugin;
- error_log('hallo');
}
else {
- $plugins_classnames = array_keys($plugins);
+/*
+ $plugins_classnames = array_keys($sel_options['plugin']);
$selected_plugin = $plugins_classnames[0];
$sel_options['plugin'] = $plugins;
+*/
}
$this->js->set_onload("set_style_by_class('tr','select_definition','display','none');");
}
@@ -120,15 +124,17 @@ class uiexport {
}
// handle selector
- //$plugin_object = new $selected_plugin;
-
- //$content['description'] = $plugin_object->get_description();
-
- // fill options tab
- // TODO: do we need all options templates online?
- // NO, we can manipulate the session array of template id on xajax request
- // however, there might be other solutions... we solve this in 1.3
- //$content['plugin_options_html'] = $plugin_object->get_options_etpl();
+ if($selected_plugin) {
+ $plugin_object = new $selected_plugin;
+
+ $content['description'] = $plugin_object->get_description();
+
+ // fill options tab
+ // TODO: do we need all options templates online?
+ // NO, we can manipulate the session array of template id on xajax request
+ // however, there might be other solutions... we solve this in 1.3
+ $content['plugin_options_html'] = $plugin_object->get_options_etpl();
+ }
// fill selection tab
if ($_selection) {
@@ -169,7 +175,7 @@ class uiexport {
//error_log(__LINE__.__FILE__.'$_content: '.print_r($_content,true));
$response = new xajaxResponse();
- if ($_content['defintion'] == 'expert') {
+ if ($_content['definition'] == 'expert') {
$definition = new definition();
$definition->definition_id = $_content['definition_id'] ? $_content['definition_id'] : '';
$definition->name = $_content['name'] ? $_content['name'] : '';
@@ -247,11 +253,52 @@ class uiexport {
return $et->exec(self::_appname. '.uiexport.export_dialog',$content,$sel_options,$readonlys,$preserv,2);
}
- public function ajax_get_plugins($_appname) {
- $response = new xajaxResponse();
+ public function ajax_get_definitions($_appname, xajaxResponse &$response = null) {
+ if(is_null($response)) {
+ $response = new xajaxResponse();
+ } else {
+ $no_return = true;
+ }
+ if (!$_appname) {
+ $response->addScript("set_style_by_class('tr','select_definition','display','none');");
+ return $no_return ? '' : $response->getXML();
+ }
+
+ $definitions = new bodefinitions(array(
+ 'type' => 'export',
+ 'application' => $_appname
+ ));
+ foreach ((array)$definitions->get_definitions() as $identifier) {
+ $definition = new definition($identifier);
+ if ($title = $definition->get_title()) {
+ if (!$selected_plugin) $selected_plugin = $plugin;
+ $sel_options['definition'] .= '';
+ }
+ unset($definition);
+ }
+ unset($definitions);
+ $sel_options['definition'] .= 'ajax_get_plugins($_appname, $response);
+ } else {
+ $response->addScript("set_style_by_class('tr','select_plugin','display','none');");
+ }
+ $response->addScript('export_dialog.change_definition(document.getElementId(\'exec[definition]\'));');
+ $response->addAssign('exec[definition]','innerHTML',$sel_options['definition']);
+ $response->addScript("set_style_by_class('tr','select_definition','display','table-row');");
+ return $no_return ? '' : $response->getXML();
+ }
+
+ public function ajax_get_plugins($_appname, xajaxResponse &$response = null) {
+ if(!is_null($response)) {
+ $no_return = true;
+ } else {
+ $response = new xajaxResponse();
+ }
if (!$_appname) {
$response->addScript("set_style_by_class('tr','select_plugin','display','none');");
- return $response->getXML();
+ return $no_return ? '' : $response->getXML();
}
(array)$plugins = import_export_helper_functions::get_plugins($_appname,'export');
@@ -264,27 +311,49 @@ class uiexport {
$this->ajax_get_plugin_description($selected_plugin,$response);
$response->addAssign('exec[plugin]','innerHTML',$sel_options['plugin']);
$response->addScript("set_style_by_class('tr','select_plugin','display','table-row');");
- return $response->getXML();
+ return $no_return ? '' : $response->getXML();
}
- public function ajax_get_plugin_description($_plugin,$_response=false) {
- $response = $_response ? $_response : new xajaxResponse();
- if (!$_plugin) return $response->getXML();
+ public function ajax_get_definition_description($_definition, xajaxResponse &$response=null) {
+ $no_return = !is_null($response);
+ if(is_null($response)) {
+ $response = new xajaxResponse();
+ }
+ if (!$_definition) return $response->getXML();
+ $_object = new definition($_definition);
+ if (is_a($_object, 'definition')) {
+ $description = $_object->description;
+ $response->assign('exec[plugin_description]','innerHTML',$description);
+ }
+ unset ($_object);
+
+ return $no_return ? '' : $response->getXML();
+ }
+
+ public function ajax_get_plugin_description($_plugin,&$_response=false) {
+ $no_return = !is_null($response);
+ if(is_null($response)) {
+ $response = new xajaxResponse();
+ }
+ if (!$_plugin) return $no_return ? '' : $response->getXML();
$plugin_object = new $_plugin;
if (is_a($plugin_object, 'iface_export_plugin')) {
$description = $plugin_object->get_description();
- $_response->addAssign('plugin_description','style.width','300px');
- $_response->addAssign('plugin_description','innerHTML',$description);
+ $_response->addAssign('exec[plugin_description]','innerHTML',$description);
}
unset ($plugin_object);
- return $_response ? '' : $response->getXML();
+ return $no_return ? '' : $response->getXML();
}
public function ajax_get_plugin_options($_plugin,$_response=false) {
+ $no_return = !is_null($response);
+ if(is_null($response)) {
+ $response = new xajaxResponse();
+ }
$response = $_response ? $_response : new xajaxResponse();
- if (!$_plugin) return $response->getXML();
+ if (!$_plugin) return $no_return ? '' : $response->getXML();
$plugin_object = new $_plugin;
if (is_a($plugin_object, 'iface_export_plugin')) {
@@ -325,4 +394,4 @@ class uiexport {
public function ajax_get_template($_name) {
}
-} // end class uiexport
\ No newline at end of file
+} // end class uiexport
diff --git a/importexport/js/export_dialog.js b/importexport/js/export_dialog.js
index c42e8e27b6..a887f29b90 100644
--- a/importexport/js/export_dialog.js
+++ b/importexport/js/export_dialog.js
@@ -13,16 +13,19 @@ function export_dialog() {
this.change_definition = function(sel_obj) {
if(sel_obj.value == 'expert') {
+ xajax_doXMLHTTP('importexport.uiexport.ajax_get_plugins',document.getElementById('exec[appname]') ? document.getElementById('exec[appname]').value : this.appname);
// next two lines fix some strange layout bug
- set_style_by_class('tr','select_definition','display','none');
- set_style_by_class('tr','select_definition','display','inline');
- set_style_by_class('tr','select_plugin','display','inline');
+ //set_style_by_class('tr','select_definition','display','none');
+ //set_style_by_class('tr','select_definition','display','inline');
+ set_style_by_class('tr','select_plugin','display','table-row');
set_style_by_class('tr','save_definition','display','inline');
}
else {
+ xajax_doXMLHTTP('importexport.uiexport.ajax_get_definition_description',sel_obj.value);
set_style_by_class('tr','select_plugin','display','none');
set_style_by_class('tr','save_definition','display','none');
}
};
+ this.appname = '';
}
-var export_dialog = new export_dialog();
\ No newline at end of file
+var export_dialog = new export_dialog();
diff --git a/importexport/setup/etemplates.inc.php b/importexport/setup/etemplates.inc.php
index 21f62634b0..946b974830 100644
--- a/importexport/setup/etemplates.inc.php
+++ b/importexport/setup/etemplates.inc.php
@@ -1,14 +1,14 @@
'importexport.export_dialog','template' => '','l
$templ_data[] = array('name' => 'importexport.export_dialog.general_tab','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:1:{s:2:"c1";s:4:",top";}i:1;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"image";s:4:"name";s:6:"export";}s:1:"B";a:2:{s:4:"type";s:8:"template";s:4:"name";s:46:"importexport.export_dialog.general_tab_content";}}}s:4:"rows";i:1;s:4:"cols";i:2;s:4:"size";s:6:",200px";s:7:"options";a:1:{i:1;s:5:"200px";}}}','size' => ',200px','style' => '','modified' => '1158223670',);
-$templ_data[] = array('name' => 'importexport.export_dialog.general_tab_content','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:6:{i:0;a:3:{s:2:"c2";s:14:"select_appname";s:2:"c3";s:17:"select_definition";s:2:"c4";s:13:"select_plugin";}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:5:"label";s:14:"some nice text";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:18:"Select application";}s:1:"B";a:4:{s:4:"type";s:6:"select";s:7:"no_lang";s:1:"1";s:4:"name";s:7:"appname";s:8:"onchange";s:69:"xajax_doXMLHTTP(\'importexport.uiexport.ajax_get_plugins\',this.value);";}}i:3;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:17:"Select definition";}s:1:"B";a:4:{s:4:"type";s:6:"select";s:7:"no_lang";s:1:"1";s:4:"name";s:10:"definition";s:8:"onchange";s:52:"export_dialog.change_definition(this); return false;";}}i:4;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:13:"Select plugin";}s:1:"B";a:4:{s:4:"type";s:6:"select";s:8:"onchange";s:80:"xajax_doXMLHTTP(\'importexport.uiexport.ajax_get_definition_options\',this.value);";s:7:"no_lang";s:1:"1";s:4:"name";s:6:"plugin";}}i:5;a:2:{s:1:"A";a:6:{s:4:"type";s:3:"box";s:4:"span";s:3:"all";s:4:"name";s:18:"plugin_description";s:6:"needed";s:1:"1";s:4:"size";s:1:"1";i:1;a:7:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:6:"needed";s:1:"1";i:1;a:4:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:6:"needed";s:1:"1";s:5:"label";s:11:"Description";}i:2;a:2:{s:4:"type";s:5:"label";s:4:"name";s:18:"plugin_description";}s:4:"name";s:11:"description";s:7:"no_lang";s:1:"1";}}s:1:"B";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:5;s:4:"cols";i:2;}}','size' => '','style' => '','modified' => '1158223021',);
+$templ_data[] = array('name' => 'importexport.export_dialog.general_tab_content','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:6:{i:0;a:3:{s:2:"c2";s:14:"select_appname";s:2:"c3";s:17:"select_definition";s:2:"c4";s:13:"select_plugin";}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:5:"label";s:14:"some nice text";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:18:"Select application";}s:1:"B";a:4:{s:4:"type";s:6:"select";s:7:"no_lang";s:1:"1";s:4:"name";s:7:"appname";s:8:"onchange";s:73:"xajax_doXMLHTTP(\'importexport.uiexport.ajax_get_definitions\',this.value);";}}i:3;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:17:"Select definition";}s:1:"B";a:4:{s:4:"type";s:6:"select";s:7:"no_lang";s:1:"1";s:4:"name";s:10:"definition";s:8:"onchange";s:52:"export_dialog.change_definition(this); return false;";}}i:4;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:13:"Select plugin";}s:1:"B";a:4:{s:4:"type";s:6:"select";s:8:"onchange";s:80:"xajax_doXMLHTTP(\'importexport.uiexport.ajax_get_definition_options\',this.value);";s:7:"no_lang";s:1:"1";s:4:"name";s:6:"plugin";}}i:5;a:2:{s:1:"A";a:6:{s:4:"type";s:3:"box";s:4:"span";s:3:"all";s:4:"name";s:18:"plugin_description";s:6:"needed";s:1:"1";s:4:"size";s:1:"1";i:1;a:7:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:6:"needed";s:1:"1";i:1;a:4:{s:4:"type";s:5:"label";s:4:"span";s:3:"all";s:6:"needed";s:1:"1";s:5:"label";s:11:"Description";}i:2;a:2:{s:4:"type";s:5:"label";s:4:"name";s:18:"plugin_description";}s:4:"name";s:11:"description";s:7:"no_lang";s:1:"1";}}s:1:"B";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:5;s:4:"cols";i:2;}}','size' => '','style' => '','modified' => '1158223021',);
$templ_data[] = array('name' => 'importexport.export_dialog.options_tab','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:1:{s:2:"c1";s:4:",top";}i:1;a:1:{s:1:"A";a:3:{s:4:"type";s:4:"html";s:4:"name";s:19:"plugin_options_html";s:7:"no_lang";s:1:"1";}}}s:4:"rows";i:1;s:4:"cols";i:1;s:4:"size";s:6:",200px";s:7:"options";a:1:{i:1;s:5:"200px";}}}','size' => ',200px','style' => '','modified' => '1158223824',);
@@ -46,6 +46,12 @@ $templ_data[] = array('name' => 'importexport.export_dialog.selection_tab','temp
$templ_data[] = array('name' => 'importexport.import_definition','template' => '','lang' => '','group' => '0','version' => '0.0.1','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:4:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:92:"Import definitions (Attension: Existing definitions with equal names will be overwritten!!!)";}}i:2;a:1:{s:1:"A";a:2:{s:4:"type";s:4:"file";s:4:"name";s:11:"import_file";}}i:3;a:1:{s:1:"A";a:3:{s:4:"type";s:6:"button";s:5:"label";s:6:"Import";s:4:"name";s:6:"import";}}}s:4:"rows";i:3;s:4:"cols";i:1;}}','size' => '','style' => '','modified' => '1150533844',);
+$templ_data[] = array('name' => 'importexport.import_dialog','template' => '','lang' => '','group' => '0','version' => '0.1','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:7:{i:0;a:1:{s:2:"h1";s:10:",!@message";}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:11:"all,message";s:4:"name";s:7:"message";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:11:"Application";}s:1:"B";a:3:{s:4:"type";s:6:"select";s:4:"name";s:7:"appname";s:8:"onchange";s:87:"xajax_doXMLHTTP(\'importexport.importexport_import_ui.ajax_get_definitions\',this.value);";}}i:3;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:28:"Please select file to import";}s:1:"B";a:3:{s:4:"type";s:4:"file";s:4:"name";s:4:"file";s:8:"onchange";s:142:"xajax_doXMLHTTP(\'importexport.importexport_import_ui.ajax_get_definitions\', document.getElementById(form::name(\'appname\')).value, this.value);";}}i:4;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:17:"Import definition";}s:1:"B";a:2:{s:4:"type";s:6:"select";s:4:"name";s:10:"definition";}}i:5;a:2:{s:1:"A";a:1:{s:4:"type";s:5:"label";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:6;a:2:{s:1:"A";a:6:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"3";s:4:"span";s:3:"all";i:1;a:3:{s:4:"type";s:6:"button";s:5:"label";s:6:"Import";s:4:"name";s:6:"import";}i:2;a:3:{s:4:"type";s:6:"button";s:4:"name";s:6:"cancel";s:5:"label";s:6:"Cancel";}i:3;a:4:{s:4:"type";s:8:"checkbox";s:4:"name";s:7:"dry-run";s:5:"label";s:9:"Test only";s:5:"align";s:5:"right";}}s:1:"B";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:6;s:4:"cols";i:2;}}','size' => '','style' => '','modified' => '1266439013',);
+
+$templ_data[] = array('name' => 'importexport.schedule_edit','template' => '','lang' => '','group' => '0','version' => '1.7.001','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:9:{i:0;a:1:{s:2:"h1";s:10:",!@message";}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:11:"all,message";s:4:"name";s:7:"message";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:4:"Type";}s:1:"B";a:2:{s:4:"type";s:6:"select";s:4:"name";s:4:"type";}}i:3;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:11:"Application";}s:1:"B";a:3:{s:4:"type";s:6:"select";s:4:"name";s:7:"appname";s:8:"onchange";s:137:"xajax_doXMLHTTP(\'importexport.importexport_schedule_ui.ajax_get_plugins\', document.getElementById(form::name(\'type\')).value, this.value);";}}i:4;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"Plugin";}s:1:"B";a:4:{s:4:"type";s:6:"select";s:4:"name";s:6:"plugin";s:4:"size";s:9:"Select...";s:8:"onchange";s:144:"xajax_doXMLHTTP(\'importexport.importexport_schedule_ui.ajax_get_definitions\', document.getElementById(form::name(\'appname\')).value, this.value);";}}i:5;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:10:"Definition";}s:1:"B";a:3:{s:4:"type";s:6:"select";s:4:"name";s:10:"definition";s:4:"size";s:9:"Select...";}}i:6;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"Target";}s:1:"B";a:3:{s:4:"type";s:4:"text";s:4:"size";s:2:"50";s:4:"name";s:6:"target";}}i:7;a:2:{s:1:"A";a:7:{s:4:"type";s:4:"grid";s:4:"data";a:4:{i:0;a:1:{s:2:"c1";s:2:"th";}i:1;a:6:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:4:"Year";}s:1:"B";a:2:{s:4:"type";s:5:"label";s:5:"label";s:5:"Month";}s:1:"C";a:2:{s:4:"type";s:5:"label";s:5:"label";s:3:"Day";}s:1:"D";a:2:{s:4:"type";s:5:"label";s:5:"label";s:11:"Day of week";}s:1:"E";a:2:{s:4:"type";s:5:"label";s:5:"label";s:4:"Hour";}s:1:"F";a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"Minute";}}i:2;a:6:{s:1:"A";a:3:{s:4:"type";s:4:"text";s:4:"name";s:4:"year";s:4:"size";s:1:"5";}s:1:"B";a:3:{s:4:"type";s:4:"text";s:4:"name";s:5:"month";s:4:"size";s:1:"5";}s:1:"C";a:3:{s:4:"type";s:4:"text";s:4:"name";s:3:"day";s:4:"size";s:1:"5";}s:1:"D";a:4:{s:4:"type";s:4:"text";s:4:"name";s:3:"dow";s:5:"align";s:6:"center";s:4:"size";s:1:"5";}s:1:"E";a:3:{s:4:"type";s:4:"text";s:4:"name";s:4:"hour";s:4:"size";s:1:"5";}s:1:"F";a:3:{s:4:"type";s:4:"text";s:4:"name";s:3:"min";s:4:"size";s:1:"5";}}i:3;a:6:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:1:"3";s:5:"label";s:11:"(* for 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:2:{s:4:"type";s:5:"label";s:5:"label";s:12:"(0-6, 0=Sun)";}s:1:"E";a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"(0-23)";}s:1:"F";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:3;s:4:"cols";i:6;s:4:"name";s:8:"schedule";s:4:"span";s:3:"all";s:7:"options";a:0:{}}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:8;a:2:{s:1:"A";a:5:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";s:4:"span";s:3:"all";i:1;a:3:{s:4:"type";s:6:"button";s:5:"label";s:4:"Save";s:4:"name";s:4:"save";}i:2;a:4:{s:4:"type";s:6:"button";s:4:"name";s:6:"cancel";s:5:"label";s:6:"Cancel";s:7:"onclick";s:13:"self.close();";}}s:1:"B";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:8;s:4:"cols";i:2;}}','size' => '','style' => '','modified' => '1267036378',);
+
+$templ_data[] = array('name' => 'importexport.schedule_index','template' => '','lang' => '','group' => '0','version' => '1.7.001','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:4:{i:0;a:1:{s:2:"h1";s:6:",!@msg";}i:1;a:1:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:11:"all,message";s:4:"name";s:4:"@msg";}}i:2;a:1:{s:1:"A";a:6:{s:4:"type";s:4:"grid";s:4:"name";s:9:"scheduled";s:7:"options";a:0:{}s:4:"data";a:3:{i:0;a:2:{s:2:"c1";s:2:"th";s:2:"c2";s:4:",top";}i:1;a:7:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:4:"Type";}s:1:"B";a:2:{s:4:"type";s:5:"label";s:5:"label";s:11:"Application";}s:1:"C";a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"Plugin";}s:1:"D";a:2:{s:4:"type";s:5:"label";s:5:"label";s:10:"Definition";}s:1:"E";a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"Target";}s:1:"F";a:4:{s:4:"type";s:4:"vbox";s:4:"size";s:6:"2,,0,0";i:1;a:2:{s:4:"type";s:5:"label";s:5:"label";s:8:"Next Run";}i:2;a:2:{s:4:"type";s:5:"label";s:5:"label";s:8:"Schedule";}}s:1:"G";a:1:{s:4:"type";s:5:"label";}}i:2;a:7:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:4:"name";s:12:"${row}[type]";}s:1:"B";a:3:{s:4:"type";s:10:"select-app";s:4:"name";s:15:"${row}[appname]";s:8:"readonly";s:1:"1";}s:1:"C";a:4:{s:4:"type";s:6:"select";s:7:"no_lang";s:1:"1";s:4:"name";s:14:"${row}[plugin]";s:8:"readonly";s:1:"1";}s:1:"D";a:3:{s:4:"type";s:6:"select";s:4:"name";s:18:"${row}[definition]";s:8:"readonly";s:1:"1";}s:1:"E";a:3:{s:4:"type";s:5:"label";s:7:"no_lang";s:1:"1";s:4:"name";s:14:"${row}[target]";}s:1:"F";a:4:{s:4:"type";s:4:"vbox";s:4:"size";s:6:"2,,0,0";i:1;a:3:{s:4:"type";s:9:"date-time";s:4:"name";s:12:"${row}[next]";s:8:"readonly";s:1:"1";}i:2;a:3:{s:4:"type";s:5:"label";s:7:"no_lang";s:1:"1";s:4:"name";s:13:"${row}[times]";}}s:1:"G";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:6:"2,,0,0";i:1;a:4:{s:4:"type";s:6:"button";s:4:"size";s:4:"edit";s:4:"name";s:21:"edit[${row_cont[id]}]";s:7:"onclick";s:198:"window.open(egw::link(\'/index.php\',\'menuaction=importexport.importexport_schedule_ui.edit&id={$row_cont[id]}\'),\'_blank\',\'dependent=yes,width=600,height=450,scrollbars=yes,status=yes\'); return false;";}i:2;a:3:{s:4:"type";s:6:"button";s:4:"size";s:6:"delete";s:4:"name";s:23:"delete[{$row_cont[id]}]";}}}}s:4:"rows";i:2;s:4:"cols";i:7;}}i:3;a:1:{s:1:"A";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"1";s:4:"span";s:3:"all";i:1;a:4:{s:4:"type";s:6:"button";s:5:"label";s:3:"add";s:4:"name";s:3:"add";s:7:"onclick";s:179:"window.open(egw::link(\'/index.php\',\'menuaction=importexport.importexport_schedule_ui.edit\'),\'_blank\',\'dependent=yes,width=600,height=450,scrollbars=yes,status=yes\'); return false;";}}}}s:4:"rows";i:3;s:4:"cols";i:1;}}','size' => '','style' => '','modified' => '1267034207',);
+
$templ_data[] = array('name' => 'importexport.wizzardbox','template' => '','lang' => '','group' => '0','version' => '0.0.1','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:3:{s:2:"c2";s:7:",bottom";s:2:"c1";s:4:",top";s:1:"A";s:4:"100%";}i:1;a:1:{s:1:"A";a:5:{s:4:"type";s:4:"hbox";s:7:"no_lang";s:1:"1";s:4:"size";s:1:"2";i:1;a:4:{s:4:"type";s:4:"hbox";s:7:"no_lang";s:1:"1";s:4:"size";s:1:"1";i:1;a:3:{s:4:"type";s:5:"image";s:7:"no_lang";s:1:"1";s:4:"name";s:12:"importexport";}}i:2;a:4:{s:4:"type";s:8:"groupbox";s:4:"size";s:1:"1";i:1;a:2:{s:4:"type";s:8:"template";s:4:"name";s:15:"wizzard_content";}s:4:"span";s:16:",wizzard_content";}}}i:2;a:1:{s:1:"A";a:6:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";s:4:"span";s:3:"all";i:1;a:5:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"3";i:1;a:4:{s:4:"type";s:6:"button";s:4:"name";s:16:"button[previous]";s:5:"label";s:8:"previous";s:7:"onclick";s:37:"xajax_eT_wrapper(this); return false;";}i:2;a:4:{s:4:"type";s:6:"button";s:4:"name";s:12:"button[next]";s:5:"label";s:4:"next";s:7:"onclick";s:37:"xajax_eT_wrapper(this); return false;";}i:3;a:4:{s:4:"type";s:6:"button";s:4:"name";s:14:"button[finish]";s:5:"label";s:6:"finish";s:7:"onclick";s:37:"xajax_eT_wrapper(this); return false;";}}i:2;a:5:{s:4:"type";s:6:"button";s:4:"name";s:14:"button[cancel]";s:5:"label";s:6:"cancel";s:7:"onclick";s:29:"window.close(); return false;";s:5:"align";s:5:"right";}s:5:"align";s:5:"right";}}}s:4:"rows";i:2;s:4:"cols";i:1;s:4:"size";s:4:",400";s:7:"options";a:1:{i:1;s:3:"400";}}}','size' => ',400','style' => '.wizzard_content fieldset {
height: 347px;
width: 250px;
From 822230bf572a897f06dbfc21cc7967758461c779 Mon Sep 17 00:00:00 2001
From: Nathan Gray
Date: Thu, 25 Feb 2010 23:14:24 +0000
Subject: [PATCH 031/334] New classes for importing and scheduling
---
.../inc/class.importexport_import_ui.inc.php | 134 ++++++++
.../class.importexport_schedule_ui.inc.php | 286 ++++++++++++++++++
2 files changed, 420 insertions(+)
create mode 100644 importexport/inc/class.importexport_import_ui.inc.php
create mode 100644 importexport/inc/class.importexport_schedule_ui.inc.php
diff --git a/importexport/inc/class.importexport_import_ui.inc.php b/importexport/inc/class.importexport_import_ui.inc.php
new file mode 100644
index 0000000000..1f33d425bb
--- /dev/null
+++ b/importexport/inc/class.importexport_import_ui.inc.php
@@ -0,0 +1,134 @@
+ true,
+ 'download' => true,
+ );
+
+ /**
+ * holds all import plugins from all apps
+ *
+ * @var array
+ */
+ private $plugins;
+
+ public function __construct() {
+ $GLOBALS['egw']->js->validate_file('.','import_dialog','importexport');
+ $this->plugins = import_export_helper_functions::get_plugins('all','import');
+ $GLOBALS['egw_info']['flags']['include_xajax'] = true;
+ }
+
+ /**
+ * Step user through importing their file
+ */
+ public function import_dialog($content = array()) {
+ $appname = $_GET['appname'] ? $_GET['appname'] : $content['appname'];
+ $definition = $_GET['definition'] ? $_GET['definition'] : $content['definition'];
+
+ if($content['import'] && $definition) {
+ try {
+ $definition_obj = new definition($content['definition']);
+ if($content['dry-run']) {
+ $definition_obj->plugin_options = $definition_obj->plugin_options + array('dry_run' => true);
+ }
+ $plugin = new $definition_obj->plugin;
+ $file = fopen($content['file']['tmp_name'], 'r');
+
+ // Some of the translation, conversion, etc look here
+ $GLOBALS['egw_info']['flags']['currentapp'] = $appname;
+ $count = $plugin->import($file, $definition_obj);
+
+ $this->message = lang('%1 records imported successfully', $count);
+ if(count($plugin->get_errors())) {
+ $this->message .= "\n".lang('Unable to import:');
+ foreach($plugin->get_errors() as $record => $message) {
+ $this->message .= "\n$record: $message";
+ }
+ }
+ } catch (Exception $e) {
+ $this->message = $e->getMessage();
+ }
+ }
+ $data['appname'] = $appname;
+ $data['definition'] = $definition;
+ $sel_options = self::get_select_options($data);
+
+ $data['message'] = $this->message;
+
+ $template = new etemplate('importexport.import_dialog');
+ $template->exec('importexport.importexport_import_ui.import_dialog', $data, $sel_options, $readonlys, $preserve, 2);
+ }
+
+ /**
+ * Get options for select boxes
+ */
+ public static function get_select_options(Array $data) {
+ $options = array();
+
+ (array)$apps = import_export_helper_functions::get_apps('import');
+ $options['appname'] = array('' => lang('Select one')) + array_combine($apps,$apps);
+
+ if($data['appname']) {
+ $options['definition'] = array();
+
+ if($data['file'] && !is_array($data['file'])) {
+ $extension = substr($data['file'], -3);
+ }
+ $definitions = new bodefinitions(array(
+ 'type' => 'import',
+ 'application' => $data['appname']
+ ));
+ foreach ((array)$definitions->get_definitions() as $identifier) {
+ $definition = new definition($identifier);
+ if ($title = $definition->get_title()) {
+ $options['definition'][$title] = $title;
+ }
+ unset($definition);
+ }
+ unset($definitions);
+ }
+
+ return $options;
+ }
+
+ /**
+ * Get definitions via ajax
+ */
+ public function ajax_get_definitions($appname, $file=null) {
+ $options = self::get_select_options(array('appname'=>$appname, 'file'=>$file));
+ if(is_array($options['definition'])) {
+ foreach ($options['definition'] as $value => $title) {
+ $sel_options['definition'] .= '';
+ }
+ }
+ $response = new xajaxResponse();
+ $response->addScript('import_dialog.change_definition(document.getElementId(\'exec[definition]\'));');
+ $response->addAssign('exec[definition]','innerHTML',$sel_options['definition']);
+ return $response->getXML();
+ }
+ }
+?>
diff --git a/importexport/inc/class.importexport_schedule_ui.inc.php b/importexport/inc/class.importexport_schedule_ui.inc.php
new file mode 100644
index 0000000000..e3200a8250
--- /dev/null
+++ b/importexport/inc/class.importexport_schedule_ui.inc.php
@@ -0,0 +1,286 @@
+ true,
+ 'edit' => true,
+ );
+
+ protected static $template;
+
+ public function __construct() {
+ $this->template = new etemplate();
+ }
+
+ public function index($content = array()) {
+
+ if($content['scheduled']['delete']) {
+ $key = key($content['scheduled']['delete']);
+ ExecMethod('phpgwapi.asyncservice.cancel_timer', $key);
+ }
+ $async_list = ExecMethod('phpgwapi.asyncservice.read', 'importexport%');
+ foreach($async_list as $id => $async) {
+ $data['scheduled'][] = $async['data'] + array(
+ 'id' => $id,
+ 'next' => $async['next'],
+ 'times' => str_replace("\n", '', print_r($async['times'], true)),
+ );
+ }
+ array_unshift($data['scheduled'], false);
+ $sel_options = self::get_select_options($data);
+ $this->template->read('importexport.schedule_index');
+
+ $GLOBALS['egw_info']['flags']['app_header'] = lang('Schedule import / export');
+ $this->template->exec('importexport.importexport_schedule_ui.index', $data, $sel_options, $readonlys, $preserve);
+ }
+
+ public function edit($content = array()) {
+ $id = $_GET['id'] ? $_GET['id'] : $content['id'];
+ unset($content['id']);
+
+ $data = $content;
+
+ // Deal with incoming
+ if($content['save'] && self::check_target($content) === true) {
+ unset($content['save']);
+ ExecMethod('phpgwapi.asyncservice.cancel_timer', $id);
+ $id = self::generate_id($content);
+ $schedule = $content['schedule'];
+ unset($content['schedule']);
+
+ // Fill in * for any left blank
+ foreach($schedule as $key => &$value) {
+ if($value == '') $value = '*';
+ }
+ $result = ExecMethod2('phpgwapi.asyncservice.set_timer',
+ $schedule,
+ $id,
+ 'importexport.importexport_schedule_ui.exec',
+ $content
+ );
+ if($result) {
+ $GLOBALS['egw']->js->set_onload('window.opener.location.reload(); self.close();');
+ } else {
+ $data['message'] = lang('Unable to schedule');
+ unset($id);
+ }
+ }
+
+ if($id) {
+ $preserve['id'] = $id;
+ $async = ExecMethod('phpgwapi.asyncservice.read', $id);
+ if(is_array($async[$id]['data'])) {
+ $data += $async[$id]['data'];
+ $data['schedule'] = $async[$id]['times'];
+ } else {
+ $data['message'] = lang('Schedule not found');
+ }
+ } else {
+ $data['type'] = 'import';
+ }
+
+ if($data['target'] && $data['type']) {
+ $file_check = self::check_target($data);
+ if($file_check !== true) $data['message'] .= ($data['message'] ? "\n" . $file_check : $file_check);
+ }
+
+ $sel_options = self::get_select_options($data);
+
+ $GLOBALS['egw_info']['flags']['app_header'] = lang('Schedule import / export');
+ $this->template->read('importexport.schedule_edit');
+ $this->template->exec('importexport.importexport_schedule_ui.edit', $data, $sel_options, $readonlys, $preserve, 2);
+ }
+
+ /**
+ * Get options for select boxes
+ */
+ public static function get_select_options(Array $data) {
+ $options = array(
+ 'type' => array(
+ 'import' => lang('import'),
+ 'export' => lang('export')
+ )
+ );
+
+ (array)$apps = import_export_helper_functions::get_apps($data['type'] ? $data['type'] : 'all');
+ if(count($apps)) {
+ $options['appname'] = array('' => lang('Select one')) + array_combine($apps,$apps);
+ }
+
+ if($data['appname']) {
+ $plugins = import_export_helper_functions::get_plugins($data['appname'], $data['type']);
+ if(is_array($plugins[$data['appname']][$data['type']])) {
+ foreach($plugins[$data['appname']][$data['type']] as $key => $title) {
+ $options['plugin'][$key] = $title;
+ }
+ }
+ } else {
+ $plugins = import_export_helper_functions::get_plugins('all', $data['type'] ? $data['type'] : 'all');
+ if(is_array($plugins)) {
+ foreach($plugins as $appname => $_types) {
+ foreach($_types as $type => $plugins) {
+ foreach($plugins as $key => $title) {
+ $options['plugin'][$key] = $title;
+ }
+ }
+ }
+ }
+ }
+
+ $options['definition'] = array();
+
+ if($data['file'] && !is_array($data['file'])) {
+ $extension = substr($data['file'], -3);
+ }
+
+ // If the query isn't started with something, bodefinitions won't load the definitions
+ $query = array('definition_id');
+ if($data['type']) $query['type'] = $data['type'];
+ if($data['application']) $query['application'] = $data['application'];
+ if($data['plugin']) $query['plugin'] = $data['plugin'];
+ $definitions = new bodefinitions($query);
+ foreach ((array)$definitions->get_definitions() as $identifier) {
+ $definition = new definition($identifier);
+ if ($title = $definition->get_title()) {
+ $options['definition'][$title] = $title;
+ }
+ unset($definition);
+ }
+ unset($definitions);
+
+ return $options;
+ }
+
+ /**
+ * Generate a async key
+ */
+ public static function generate_id($data) {
+
+ $query = array(
+ 'name' => $data['definition']
+ );
+
+ $definitions = new bodefinitions($query);
+ $definition_list = ((array)$definitions->get_definitions());
+
+ $id = 'importexport'.$definition_list[0].time();
+ return $id;
+ }
+
+ /**
+ * Get plugins via ajax
+ */
+ public function ajax_get_plugins($type, $appname, &$response = null) {
+ if($response) {
+ $return = false;
+ } else {
+ $response = new xajaxResponse();
+ }
+ $options = self::get_select_options(array('type' => $type, 'appname'=>$appname));
+ if(is_array($options['plugins'])) {
+ foreach ($options['plugins'] as $value => $title) {
+ $response->addScript("selectbox_add_option('exec[plugin]','$title', '$value',false);");
+ }
+ }
+ return $response->getXML();
+ }
+
+ /**
+ * Get definitions via ajax
+ */
+ public function ajax_get_definitions($appname, $plugin) {
+ $options = self::get_select_options(array('appname'=>$appname, 'plugin'=>$plugin));
+ if(is_array($options['definition'])) {
+ foreach ($options['definition'] as $value => $title) {
+ $sel_options['definition'] .= '';
+ }
+ }
+ $response = new xajaxResponse();
+ $response->addAssign('exec[definition]','innerHTML',$sel_options['definition']);
+ return $response->getXML();
+ }
+
+ /**
+ * Check that the target is valid for the type (readable or writable)
+ * $data should contain target & type
+ */
+ public static function check_target(Array $data) {
+ if ($data['type'] == 'import' && !is_readable($data['target']))
+ {
+ return $data['target']. ' is not readable';
+ }
+ elseif ($data['type'] == 'export' && !is_writable($data['target'])) {
+ return $data['target']. ' is not writable';
+ }
+
+ return true;
+ }
+
+ /**
+ * Execute a scheduled import or export
+ */
+ public static function exec($data) {
+ ob_start();
+
+ // check file
+ $file_check = self::check_target($data);
+ if($file_check !== true) {
+ fwrite(STDERR,'importexport_schedule: ' . date('c') . ": $file_check \n");
+ exit();
+ }
+
+ $definition = new definition($data['definition']);
+ if( $definition->get_identifier() < 1 ) {
+ fwrite(STDERR,'importexport_schedule: ' . date('c') . ": Definition not found! \n");
+ exit();
+ }
+
+ $GLOBALS['egw_info']['flags']['currentapp'] = $definition->application;
+
+ require_once(EGW_INCLUDE_ROOT . "/$definition->application/importexport/class.$definition->plugin.inc.php");
+ $po = new $definition->plugin;
+
+ $type = $data['type'];
+ if($resource = fopen( $data['target'], $data['type'] == 'import' ? 'r' : 'w' )) {
+ $po->$type( $resource, $definition );
+
+ fclose($resource);
+ } else {
+ fwrite(STDERR,'importexport_schedule: ' . date('c') . ": Definition not found! \n");
+ }
+
+ if($po->get_errors()) {
+ fwrite(STDERR, 'importexport_schedule: ' . date('c') . ": Import errors:\n#\tError\n");
+ foreach($po->get_errors() as $record => $error) {
+ fwrite(STDERR, "$record\t$error\n");
+ }
+ }
+
+ $contents = ob_get_contents();
+ if($contents) {
+ fwrite(STDOUT,'importexport_schedule: ' . date('c') . ": \n".$contents);
+ }
+ ob_end_clean();
+ }
+ }
+?>
From c6a2c8bbcc8a19a13c041cd62d8db5e02d5f054b Mon Sep 17 00:00:00 2001
From: Nathan Gray
Date: Thu, 25 Feb 2010 23:18:45 +0000
Subject: [PATCH 032/334] Changes for importexport - Fix wizard so you can
define import definitions - Change import so an update with no differences
will not change anything
---
.../class.import_contacts_csv.inc.php | 70 ++++++--
...class.wizzard_import_contacts_csv.inc.php} | 152 ++++++++++++++++--
addressbook/setup/etemplates.inc.php | 10 +-
3 files changed, 202 insertions(+), 30 deletions(-)
rename addressbook/importexport/{class.wizzard_addressbook_csv_import.inc.php => class.wizzard_import_contacts_csv.inc.php} (50%)
diff --git a/addressbook/importexport/class.import_contacts_csv.inc.php b/addressbook/importexport/class.import_contacts_csv.inc.php
index 4ccbf28c69..081b1bbfb1 100644
--- a/addressbook/importexport/class.import_contacts_csv.inc.php
+++ b/addressbook/importexport/class.import_contacts_csv.inc.php
@@ -46,14 +46,14 @@ class import_contacts_csv implements iface_import_plugin {
/**
* actions wich could be done to data entries
*/
- private static $actions = array( 'none', 'update', 'insert', 'delete', );
+ protected static $actions = array( 'none', 'update', 'insert', 'delete', );
/**
* conditions for actions
*
* @var array
*/
- private static $conditions = array( 'exists', 'greater', 'greater or equal', );
+ protected static $conditions = array( 'exists', 'greater', 'greater or equal', );
/**
* @var definition
@@ -65,6 +65,11 @@ class import_contacts_csv implements iface_import_plugin {
*/
private $bocontacts;
+ /**
+ * For figuring out if a contact has changed
+ */
+ protected $tracking;
+
/**
* @var bool
*/
@@ -80,6 +85,11 @@ class import_contacts_csv implements iface_import_plugin {
*/
private $user = null;
+ /**
+ * List of import errors
+ */
+ protected $errors = array();
+
/**
* imports entries according to given definition object.
* @param resource $_stream
@@ -104,6 +114,9 @@ class import_contacts_csv implements iface_import_plugin {
// fetch the addressbook bo
$this->bocontacts = new addressbook_bo();
+ // Get the tracker for changes
+ $this->tracking = new addressbook_tracking($this->bocontacts);
+
// set FieldMapping.
$import_csv->mapping = $_definition->plugin_options['field_mapping'];
@@ -111,15 +124,25 @@ class import_contacts_csv implements iface_import_plugin {
$import_csv->conversion = $_definition->plugin_options['field_conversion'];
//check if file has a header lines
- if ( isset( $_definition->plugin_options['num_header_lines'] ) ) {
+ if ( isset( $_definition->plugin_options['num_header_lines'] ) && $_definition->plugin_options['num_header_lines'] > 0) {
$import_csv->skip_records($_definition->plugin_options['num_header_lines']);
+ } elseif(isset($_definition->plugin_options['has_header_line']) && $_definition->plugin_options['has_header_line']) {
+ // First method is preferred
+ $import_csv->skip_records(1);
}
// set eventOwner
$_definition->plugin_options['contact_owner'] = isset( $_definition->plugin_options['contact_owner'] ) ?
$_definition->plugin_options['contact_owner'] : $this->user;
+ // Start counting successes
+ $count = 0;
+
+ // Failures
+ $this->errors = array();
+
while ( $record = $import_csv->get_record() ) {
+ $success = false;
// don't import empty contacts
if( count( array_unique( $record ) ) < 2 ) continue;
@@ -127,7 +150,6 @@ class import_contacts_csv implements iface_import_plugin {
if ( $_definition->plugin_options['contact_owner'] != -1 ) {
$record['owner'] = $_definition->plugin_options['contact_owner'];
} else unset( $record['owner'] );
-
if ( $_definition->plugin_options['conditions'] ) {
foreach ( $_definition->plugin_options['conditions'] as $condition ) {
switch ( $condition['type'] ) {
@@ -148,11 +170,11 @@ class import_contacts_csv implements iface_import_plugin {
if ( !is_array( $record['cat_id'] ) ) $record['cat_id'] = explode( ',', $record['cat_id'] );
$record['cat_id'] = implode( ',', array_unique( array_merge( $record['cat_id'], $contact['cat_id'] ) ) );
}
- $this->action( $action['action'], $record );
+ $success = $this->action( $action['action'], $record, $import_csv->get_current_position() );
}
} else {
$action = $condition['false'];
- $this->action( $action['action'], $record );
+ $success = ($this->action( $action['action'], $record, $import_csv->get_current_position() ));
}
break;
@@ -165,9 +187,11 @@ class import_contacts_csv implements iface_import_plugin {
}
} else {
// unconditional insert
- $this->action( 'insert', $record );
+ $success = $this->action( 'insert', $record, $import_csv->get_current_position() );
}
+ if($success) $count++;
}
+ return $count;
}
/**
@@ -177,16 +201,31 @@ class import_contacts_csv implements iface_import_plugin {
* @param array $_data contact data for the action
* @return bool success or not
*/
- private function action ( $_action, $_data ) {
+ private function action ( $_action, $_data, $record_num = 0 ) {
switch ($_action) {
case 'none' :
return true;
case 'update' :
+ // Only update if there are changes
+ $old = $this->bocontacts->read($_data['id']);
+
+ // Merge to deal with fields not in import record
+ $_data = array_merge($old, $_data);
+ $changed = $this->tracking->changed_fields($_data, $old);
+ if(count($changed) == 0) {
+ return true;
+ }
+ // Fall through
case 'insert' :
if ( $this->dry_run ) {
print_r($_data);
+ return true;
} else {
- return $this->bocontacts->save( $_data );
+ $result = $this->bocontacts->save( $_data, $this->is_admin);
+ if(!$result) {
+ $this->errors[$record_num] = $this->bocontacts->error;
+ }
+ return $result;
}
case 'delete' :
}
@@ -198,7 +237,7 @@ class import_contacts_csv implements iface_import_plugin {
* @return string name
*/
public static function get_name() {
- return lang('Addressbook CSV export');
+ return lang('Addressbook CSV import');
}
/**
@@ -244,5 +283,16 @@ class import_contacts_csv implements iface_import_plugin {
// lets do it!
}
+ /**
+ * Returns errors that were encountered during importing
+ * Maximum of one error message per record, but you can append if you need to
+ *
+ * @return Array (
+ * record_# => error message
+ * )
+ */
+ public function get_errors() {
+ return $this->errors;
+ }
} // end of iface_export_plugin
?>
diff --git a/addressbook/importexport/class.wizzard_addressbook_csv_import.inc.php b/addressbook/importexport/class.wizzard_import_contacts_csv.inc.php
similarity index 50%
rename from addressbook/importexport/class.wizzard_addressbook_csv_import.inc.php
rename to addressbook/importexport/class.wizzard_import_contacts_csv.inc.php
index c84db13863..53a14b353b 100644
--- a/addressbook/importexport/class.wizzard_addressbook_csv_import.inc.php
+++ b/addressbook/importexport/class.wizzard_import_contacts_csv.inc.php
@@ -9,9 +9,9 @@
* @version $Id: $
*/
-require_once(EGW_INCLUDE_ROOT.'/addressbook/inc/class.addressbook_csv_import.inc.php');
+require_once(EGW_INCLUDE_ROOT.'/addressbook/importexport/class.import_contacts_csv.inc.php');
-class wizzard_addressbook_csv_import extends addressbook_csv_import
+class wizzard_import_contacts_csv extends import_contacts_csv
{
var $steps;
@@ -19,15 +19,15 @@ class wizzard_addressbook_csv_import extends addressbook_csv_import
/**
* constructor
*/
- function wizzard_addressbook_csv_import()
+ function __construct()
{
$this->steps = array(
'wizzard_step30' => lang('Load Sample file'),
'wizzard_step40' => lang('Choose seperator and charset'),
'wizzard_step50' => lang('Manage mapping'),
+ 'wizzard_step55' => lang('Edit conditions'),
'wizzard_step60' => lang('Choose owner of imported data'),
);
- $this->__construct();
}
function wizzard_step30(&$content, &$sel_options, &$readonlys, &$preserv)
@@ -39,9 +39,13 @@ class wizzard_addressbook_csv_import extends addressbook_csv_import
switch (array_search('pressed', $content['button']))
{
case 'next':
- error_log(print_r($content,true));
- $file = fopen ($content['file']['tmp_name'],'rb');
-
+ // Move sample file to temp
+ if($content['file']['tmp_name']) {
+ $csvfile = tempnam($GLOBALS['egw_info']['server']['temp_dir'],$content['plugin']."_");
+ move_uploaded_file($content['file']['tmp_name'], $csvfile);
+ $GLOBALS['egw']->session->appsession('csvfile','',$csvfile);
+ }
+ unset($content['file']);
return $GLOBALS['egw']->uidefinitions->get_step($content['step'],1);
case 'previous' :
return $GLOBALS['egw']->uidefinitions->get_step($content['step'],-1);
@@ -82,7 +86,15 @@ class wizzard_addressbook_csv_import extends addressbook_csv_import
switch (array_search('pressed', $content['button']))
{
case 'next':
- return $GLOBALS['egw']->uidefinitions->get_step($content['step'],1);
+ // Process sample file for fields
+ if (($handle = fopen($GLOBALS['egw']->session->appsession('csvfile'), "rb")) !== FALSE) {
+ $data = fgetcsv($handle, 8000, $content['fieldsep']);
+ $content['csv_fields'] = translation::convert($data,$content['charset']);
+ return $GLOBALS['egw']->uidefinitions->get_step($content['step'],1);
+ } elseif($content['plugin_options']['csv_fields']) {
+ $content['csv_fields'] = $content['plugin_options']['csv_fields'];
+ }
+ return $this->wizzard_step40($content,$sel_options,$readonlys,$preserv);
case 'previous' :
return $GLOBALS['egw']->uidefinitions->get_step($content['step'],-1);
case 'finish':
@@ -96,6 +108,21 @@ class wizzard_addressbook_csv_import extends addressbook_csv_import
{
$content['msg'] = $this->steps['wizzard_step40'];
$content['step'] = 'wizzard_step40';
+
+ // If editing an existing definition, these will be in plugin_options
+ if(!$content['fieldsep'] && $content['plugin_options']['fieldsep']) {
+ $content['fieldsep'] = $content['plugin_options']['fieldsep'];
+ }
+ if(!$content['charset'] && $content['plugin_options']['charset']) {
+ $content['charset'] = $content['plugin_options']['charset'];
+ }
+ if(!$content['has_header_line'] && $content['plugin_options']['has_header_line']) {
+ $content['num_header_lines'] = 1;
+ }
+ if(!$content['num_header_lines'] && $content['plugin_options']['num_header_lines']) {
+ $content['num_header_lines'] = $content['plugin_options']['num_header_lines'];
+ }
+
$sel_options['charset'] = $GLOBALS['egw']->translation->get_installed_charsets()+
array('utf-8' => 'utf-8 (Unicode)');
$preserv = $content;
@@ -112,9 +139,12 @@ class wizzard_addressbook_csv_import extends addressbook_csv_import
if ($content['step'] == 'wizzard_step50')
{
array_shift($content['csv_fields']);
- //$content['csv_fields'] = array('csv_01','csv_02','csv_03','csv_04','csv_05','csv_06','csv_07','csv_08','csv_09','csv_10','csv_11','csv_12');
array_shift($content['field_mapping']);
- array_shift($content['field_translation']);
+ array_shift($content['field_conversion']);
+
+ foreach($content['field_conversion'] as $field => $convert) {
+ if(!trim($convert)) unset($content['field_conversion'][$field]);
+ }
switch (array_search('pressed', $content['button']))
{
@@ -134,11 +164,15 @@ class wizzard_addressbook_csv_import extends addressbook_csv_import
$content['msg'] = $this->steps['wizzard_step50'];
$content['step'] = 'wizzard_step50';
+ if(!$content['field_mapping'] && $content['plugin_options']) {
+ $content['field_mapping'] = $content['plugin_options']['field_mapping'];
+ $content['field_conversion'] = $content['plugin_options']['field_conversion'];
+ }
array_unshift($content['csv_fields'],array('row0'));
array_unshift($content['field_mapping'],array('row0'));
- array_unshift($content['field_translation'],array('row0'));
+ array_unshift($content['field_conversion'],array('row0'));
- $j = 0;
+ $j = 1;
foreach ($content['csv_fields'] as $field)
{
if(strstr($field,'no_csv_')) $j++;
@@ -146,12 +180,16 @@ class wizzard_addressbook_csv_import extends addressbook_csv_import
while ($j <= 3)
{
$content['csv_fields'][] = 'no_csv_'.$j;
- $content['field_mapping'][] = $content['field_translation'][] = '';
+ $content['field_mapping'][] = $content['field_conversion'][] = '';
$j++;
}
- $contact_fields = $this->bocontacts->get_contact_columns();
- $sel_options['field_mapping'] = array('' => lang('none')) + array_combine($contact_fields,$contact_fields);
- error_log(print_r($sel_options['field_mapping'],true));
+ $bocontacts = new addressbook_bo();
+ $contact_fields = $bocontacts->contact_fields;
+ foreach($bocontacts->customfields as $name => $data) {
+ $contact_fields['#'.$name] = $data['label'];
+ }
+ unset($addr_names['jpegphoto']); // can't cvs import that
+ $sel_options['field_mapping'] = array('' => lang('none')) + $contact_fields;
$preserv = $content;
unset ($preserv['button']);
return 'addressbook.importexport_wizzard_fieldmaping';
@@ -159,6 +197,80 @@ class wizzard_addressbook_csv_import extends addressbook_csv_import
}
+ /**
+ * Edit conditions
+ */
+ function wizzard_step55(&$content, &$sel_options, &$readonlys, &$preserv)
+ {
+ if($this->debug) error_log('addressbook.wizzard_import_contacts_csv->$content '.print_r($content,true));
+ // return from step55
+ if ($content['step'] == 'wizzard_step55')
+ {
+ array_shift($content['conditions']);
+
+ foreach($content['conditions'] as $key => &$condition) {
+ // Clear empties
+ if($condition['string'] == '') {
+ unset($content['conditions'][$key]);
+ continue;
+ }
+ }
+
+ switch (array_search('pressed', $content['button']))
+ {
+ case 'next':
+ return $GLOBALS['egw']->uidefinitions->get_step($content['step'],1);
+ case 'previous' :
+ return $GLOBALS['egw']->uidefinitions->get_step($content['step'],-1);
+ case 'finish':
+ return 'wizzard_finish';
+ case 'add':
+ return $GLOBALS['egw']->uidefinitions->get_step($content['step'],0);
+ default :
+ return $this->wizzard_step55($content,$sel_options,$readonlys,$preserv);
+ break;
+ }
+ }
+ // init step55
+ $content['msg'] = $this->steps['wizzard_step55'];
+ $content['step'] = 'wizzard_step55';
+
+ if(!$content['conditions'] && $content['plugin_options']['conditions']) {
+ $content['conditions'] = $content['plugin_options']['conditions'];
+ }
+
+ $bocontacts = new addressbook_bo();
+ $contact_fields = $bocontacts->contact_fields;
+ $sel_options['string'][''] = 'None';
+ foreach($bocontacts->customfields as $name => $data) {
+ $contact_fields['#'.$name] = $data['label'];
+ }
+ foreach($content['field_mapping'] as $field) {
+ $sel_options['string'][$field] = $contact_fields[$field];
+ }
+ $sel_options['type'] = array_combine(self::$conditions, self::$conditions);
+ $sel_options['action'] = array_combine(self::$actions, self::$actions);
+
+ // Make 3 empty conditions
+ $j = 1;
+ foreach ($content['conditions'] as $condition)
+ {
+ if(!$condition['string']) $j++;
+ }
+ while ($j <= 3)
+ {
+ $content['conditions'][] = array('string' => '');
+ $j++;
+ }
+
+ // Leave room for heading
+ array_unshift($content['conditions'], false);
+
+ $preserv = $content;
+ unset ($preserv['button']);
+ return 'addressbook.importexport_wizzard_conditions';
+ }
+
function wizzard_step60(&$content, &$sel_options, &$readonlys, &$preserv)
{
if($this->debug) error_log('addressbook.importexport.addressbook_csv_import::wizzard_step60->$content '.print_r($content,true));
@@ -168,6 +280,7 @@ class wizzard_addressbook_csv_import extends addressbook_csv_import
switch (array_search('pressed', $content['button']))
{
case 'next':
+ unset($content['csv_fields']);
return $GLOBALS['egw']->uidefinitions->get_step($content['step'],1);
case 'previous' :
return $GLOBALS['egw']->uidefinitions->get_step($content['step'],-1);
@@ -183,6 +296,13 @@ class wizzard_addressbook_csv_import extends addressbook_csv_import
$content['msg'] = $this->steps['wizzard_step60'];
$content['step'] = 'wizzard_step60';
+ if(!$content['contact_owner'] && $content['plugin_options']) {
+ $content['contact_owner'] = $content['plugin_options']['contact_owner'];
+ }
+
+ $bocontacts = new addressbook_bo();
+ $sel_options['contact_owner'] = $bocontacts->get_addressbooks(EGW_ACL_ADD);
+
$preserv = $content;
unset ($preserv['button']);
return 'addressbook.importexport_wizzard_chooseowner';
diff --git a/addressbook/setup/etemplates.inc.php b/addressbook/setup/etemplates.inc.php
index d06975e5ba..78968b3e14 100755
--- a/addressbook/setup/etemplates.inc.php
+++ b/addressbook/setup/etemplates.inc.php
@@ -2,7 +2,7 @@
/**
* eGroupWare - eTemplates for Application addressbook
* http://www.egroupware.org
- * generated by soetemplate::dump4setup() 2010-02-08 10:51
+ * generated by soetemplate::dump4setup() 2010-02-25 16:13
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package addressbook
@@ -66,13 +66,15 @@ $templ_data[] = array('name' => 'addressbook.email.rows','template' => '','lang'
$templ_data[] = array('name' => 'addressbook.export_csv_options','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:0:{}i:1;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:9:"Seperator";}s:1:"B";a:3:{s:4:"type";s:4:"text";s:4:"size";s:1:"1";s:4:"name";s:9:"seperator";}}i:2;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:9:"Enclosure";}s:1:"B";a:3:{s:4:"type";s:4:"text";s:4:"size";s:1:"1";s:4:"name";s:9:"enclosure";}}}s:4:"rows";i:2;s:4:"cols";i:2;}}','size' => '','style' => '','modified' => '1160148382',);
-$templ_data[] = array('name' => 'addressbook.importexport_wizzard_chooseowner','template' => '','lang' => '','group' => '0','version' => '0.0.1','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"name";s:3:"msg";s:7:"no_lang";s:1:"1";}}i:2;a:1:{s:1:"A";a:3:{s:4:"type";s:14:"select-account";s:4:"name";s:5:"owner";s:4:"size";s:4:"none";}}}s:4:"rows";i:2;s:4:"cols";i:1;}}','size' => '','style' => '','modified' => '1146646360',);
+$templ_data[] = array('name' => 'addressbook.importexport_wizzard_chooseowner','template' => '','lang' => '','group' => '0','version' => '0.0.1','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"name";s:3:"msg";s:7:"no_lang";s:1:"1";}}i:2;a:1:{s:1:"A";a:3:{s:4:"type";s:6:"select";s:4:"name";s:13:"contact_owner";s:4:"size";s:4:"None";}}}s:4:"rows";i:2;s:4:"cols";i:1;}}','size' => '','style' => '','modified' => '1146646360',);
-$templ_data[] = array('name' => 'addressbook.importexport_wizzard_choosesepncharset','template' => '','lang' => '','group' => '0','version' => '0.0.1','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:5:{i:0;a:1:{s:1:"B";s:5:"180px";}i:1;a:2:{s:1:"A";a:4:{s:4:"type";s:5:"label";s:7:"no_lang";s:1:"1";s:4:"name";s:3:"msg";s:4:"span";s:3:"all";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:14:"Fieldseperator";}s:1:"B";a:4:{s:4:"type";s:4:"text";s:7:"no_lang";s:1:"1";s:4:"name";s:8:"fieldsep";s:4:"size";s:1:"1";}}i:3;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:7:"Charset";}s:1:"B";a:4:{s:4:"type";s:6:"select";s:7:"no_lang";s:1:"1";s:4:"name";s:7:"charset";s:4:"span";s:9:",width180";}}i:4;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:17:"Ignore first line";}s:1:"B";a:2:{s:4:"type";s:8:"checkbox";s:4:"name";s:15:"has_header_line";}}}s:4:"rows";i:4;s:4:"cols";i:2;}}','size' => '','style' => '.width180 select { width:150px;}','modified' => '1145979153',);
+$templ_data[] = array('name' => 'addressbook.importexport_wizzard_choosesepncharset','template' => '','lang' => '','group' => '0','version' => '0.0.1','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:5:{i:0;a:1:{s:1:"B";s:5:"180px";}i:1;a:2:{s:1:"A";a:4:{s:4:"type";s:5:"label";s:7:"no_lang";s:1:"1";s:4:"name";s:3:"msg";s:4:"span";s:3:"all";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:14:"Fieldseperator";}s:1:"B";a:4:{s:4:"type";s:4:"text";s:7:"no_lang";s:1:"1";s:4:"name";s:8:"fieldsep";s:4:"size";s:1:"1";}}i:3;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:15:"Charset of file";}s:1:"B";a:4:{s:4:"type";s:6:"select";s:7:"no_lang";s:1:"1";s:4:"name";s:7:"charset";s:4:"span";s:9:",width180";}}i:4;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:20:"Header lines to skip";}s:1:"B";a:3:{s:4:"type";s:3:"int";s:4:"name";s:16:"num_header_lines";s:4:"size";s:1:"0";}}}s:4:"rows";i:4;s:4:"cols";i:2;}}','size' => '','style' => '.width180 select { width:150px;}','modified' => '1145979153',);
$templ_data[] = array('name' => 'addressbook.importexport_wizzard_choosetype','template' => '','lang' => '','group' => '0','version' => '0.0.1','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:7:"no_lang";s:1:"1";s:4:"name";s:3:"msg";}}i:2;a:1:{s:1:"A";a:3:{s:4:"type";s:6:"select";s:7:"no_lang";s:1:"1";s:4:"name";s:11:"import_type";}}}s:4:"rows";i:2;s:4:"cols";i:1;}}','size' => '','style' => '','modified' => '1145977925',);
-$templ_data[] = array('name' => 'addressbook.importexport_wizzard_fieldmaping','template' => '','lang' => '','group' => '0','version' => '0.0.1','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:4:{s:4:"type";s:5:"label";s:7:"no_lang";s:1:"1";s:4:"name";s:3:"msg";s:4:"span";s:3:"all";}}i:2;a:1:{s:1:"A";a:5:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:1:{s:2:"c1";s:2:"th";}i:1;a:3:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:9:"CSV Field";}s:1:"B";a:2:{s:4:"type";s:5:"label";s:5:"label";s:17:"Addressbook Field";}s:1:"C";a:2:{s:4:"type";s:5:"label";s:5:"label";s:11:"Translation";}}i:2;a:3:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"name";s:16:"csv_fields[$row]";s:7:"no_lang";s:1:"1";}s:1:"B";a:3:{s:4:"type";s:6:"select";s:7:"no_lang";s:1:"1";s:4:"name";s:19:"field_mapping[$row]";}s:1:"C";a:2:{s:4:"type";s:4:"text";s:4:"name";s:23:"field_translation[$row]";}}}s:4:"rows";i:2;s:4:"cols";i:3;s:7:"options";a:0:{}}}}s:4:"rows";i:2;s:4:"cols";i:1;}}','size' => '','style' => '','modified' => '1146036809',);
+$templ_data[] = array('name' => 'addressbook.importexport_wizzard_conditions','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:7:{s:4:"type";s:4:"vbox";s:4:"data";a:2:{i:0;a:0:{}i:1;a:4:{s:1:"A";a:2:{s:4:"type";s:6:"select";s:4:"name";s:14:"${row}[string]";}s:1:"B";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:6:"2,,0,0";i:1;a:2:{s:4:"type";s:6:"select";s:4:"name";s:12:"${row}[type]";}i:2;a:2:{s:4:"type";s:4:"text";s:4:"name";s:12:"${row}[op_2]";}}s:1:"C";a:2:{s:4:"type";s:6:"select";s:4:"name";s:12:"${row}[true]";}s:1:"D";a:2:{s:4:"type";s:6:"select";s:4:"name";s:13:"${row}[false]";}}}s:4:"rows";i:1;s:4:"cols";i:4;s:4:"size";s:1:"2";i:1;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:1:{s:2:"c1";s:2:"th";}i:1;a:6:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:5:"Field";}s:1:"B";a:2:{s:4:"type";s:5:"label";s:5:"label";s:9:"Condition";}s:1:"C";a:5:{s:4:"type";s:4:"vbox";s:4:"size";s:1:"2";s:4:"span";s:1:"2";i:1;a:4:{s:4:"type";s:5:"label";s:4:"span";s:1:"2";s:5:"label";s:4:"True";s:5:"align";s:6:"center";}i:2;a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:6:"2,,2,0";i:1;a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"Action";}i:2;a:3:{s:4:"type";s:5:"label";s:5:"label";s:4:"Stop";s:5:"align";s:5:"right";}}}s:1:"D";a:1:{s:4:"type";s:5:"label";}s:1:"E";a:5:{s:4:"type";s:4:"vbox";s:4:"size";s:1:"2";s:4:"span";s:1:"2";i:1;a:4:{s:4:"type";s:5:"label";s:4:"span";s:1:"2";s:5:"label";s:5:"False";s:5:"align";s:6:"center";}i:2;a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:6:"2,,2,0";i:1;a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"Action";}i:2;a:3:{s:4:"type";s:5:"label";s:5:"label";s:4:"Stop";s:5:"align";s:5:"right";}}}s:1:"F";a:1:{s:4:"type";s:5:"label";}}i:2;a:6:{s:1:"A";a:2:{s:4:"type";s:6:"select";s:4:"name";s:14:"${row}[string]";}s:1:"B";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:6:"2,,0,0";i:1;a:2:{s:4:"type";s:6:"select";s:4:"name";s:12:"${row}[type]";}i:2;a:2:{s:4:"type";s:4:"text";s:4:"name";s:12:"${row}[op_2]";}}s:1:"C";a:2:{s:4:"type";s:6:"select";s:4:"name";s:20:"${row}[true][action]";}s:1:"D";a:3:{s:4:"type";s:8:"checkbox";s:5:"align";s:6:"center";s:4:"name";s:18:"${row}[true][stop]";}s:1:"E";a:2:{s:4:"type";s:6:"select";s:4:"name";s:21:"${row}[false][action]";}s:1:"F";a:3:{s:4:"type";s:8:"checkbox";s:5:"align";s:6:"center";s:4:"name";s:19:"${row}[false][stop]";}}}s:4:"rows";i:2;s:4:"cols";i:6;s:4:"name";s:10:"conditions";s:7:"options";a:0:{}}i:2;a:5:{s:4:"type";s:6:"button";s:4:"name";s:3:"add";s:5:"label";s:3:"add";s:4:"help";s:59:"This causes a segfault... haven\'t figured out how to fix it";s:8:"disabled";s:1:"1";}}}','size' => '','style' => '','modified' => '1266963791',);
+
+$templ_data[] = array('name' => 'addressbook.importexport_wizzard_fieldmaping','template' => '','lang' => '','group' => '0','version' => '0.0.1','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:4:{s:4:"type";s:5:"label";s:7:"no_lang";s:1:"1";s:4:"name";s:3:"msg";s:4:"span";s:3:"all";}}i:2;a:1:{s:1:"A";a:5:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:1:{s:2:"c1";s:2:"th";}i:1;a:4:{s:1:"A";a:1:{s:4:"type";s:5:"label";}s:1:"B";a:2:{s:4:"type";s:5:"label";s:5:"label";s:9:"CSV Field";}s:1:"C";a:2:{s:4:"type";s:5:"label";s:5:"label";s:17:"Addressbook Field";}s:1:"D";a:2:{s:4:"type";s:5:"label";s:5:"label";s:11:"Translation";}}i:2;a:4:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:5:"label";s:6:"${row}";s:7:"no_lang";s:1:"1";}s:1:"B";a:3:{s:4:"type";s:5:"label";s:4:"name";s:16:"csv_fields[$row]";s:7:"no_lang";s:1:"1";}s:1:"C";a:3:{s:4:"type";s:6:"select";s:7:"no_lang";s:1:"1";s:4:"name";s:19:"field_mapping[$row]";}s:1:"D";a:2:{s:4:"type";s:4:"text";s:4:"name";s:22:"field_conversion[$row]";}}}s:4:"rows";i:2;s:4:"cols";i:4;s:7:"options";a:0:{}}}}s:4:"rows";i:2;s:4:"cols";i:1;}}','size' => '','style' => '','modified' => '1146036809',);
$templ_data[] = array('name' => 'addressbook.importexport_wizzard_samplefile','template' => '','lang' => '','group' => '0','version' => '0.0.1','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"name";s:3:"msg";s:7:"no_lang";s:1:"1";}}i:2;a:1:{s:1:"A";a:2:{s:4:"type";s:4:"file";s:4:"name";s:4:"file";}}}s:4:"rows";i:2;s:4:"cols";i:1;}}','size' => '','style' => '','modified' => '1146650510',);
From 841300542bc3f31538f7d0f97f2ecd5d46e29f6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Lehrke?=
Date: Fri, 26 Feb 2010 11:03:34 +0000
Subject: [PATCH 033/334] Add RDATE support to VTIMEZONE parser
---
.../inc/horde/Horde/iCalendar/vtimezone.php | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/phpgwapi/inc/horde/Horde/iCalendar/vtimezone.php b/phpgwapi/inc/horde/Horde/iCalendar/vtimezone.php
index e07bd2db2d..197e0b30f5 100644
--- a/phpgwapi/inc/horde/Horde/iCalendar/vtimezone.php
+++ b/phpgwapi/inc/horde/Horde/iCalendar/vtimezone.php
@@ -12,6 +12,7 @@
* @author Mike Cochrane
* @since Horde 3.0
* @package Horde_iCalendar
+ * @changes 2010/02/26 Joerg Lehrke : Add RDATE support (for KDE 4.x)
*/
class Horde_iCalendar_vtimezone extends Horde_iCalendar {
@@ -54,6 +55,20 @@ class Horde_iCalendar_vtimezone extends Horde_iCalendar {
return false;
}
+ $rdates = $child->getAttribute('RDATE');
+ if (!is_a($rdates, 'PEAR_Error')) {
+ foreach ($rdates as $rdate) {
+ $switch_time = $switch_time['value'];
+ $switch_year = date("Y", $switch_time);
+ if ($switch_year == $year) {
+ $t = getdate($switch_time);
+ $result['time'] = @gmmktime($t['hours'], $t['minutes'], $t['seconds'],
+ $t['mon'], $t['mday'], $t['year']);
+ return $result;
+ }
+ }
+ }
+
$rrules = $child->getAttribute('RRULE');
if (is_a($rrules, 'PEAR_Error')) {
if (!is_int($switch_time)) {
@@ -68,7 +83,7 @@ class Horde_iCalendar_vtimezone extends Horde_iCalendar {
}
$switch_year = date("Y", $switch_time);
- if ( $switch_year > $year ) {
+ if ($switch_year > $year) {
return false;
}
From 72e55f9753b4eb8d0d28aca3bca4538981ace934 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Lehrke?=
Date: Fri, 26 Feb 2010 11:04:01 +0000
Subject: [PATCH 034/334] Fix GroupDAV issues
---
phpgwapi/inc/class.groupdav.inc.php | 43 +++++++++++++++++++++--------
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/phpgwapi/inc/class.groupdav.inc.php b/phpgwapi/inc/class.groupdav.inc.php
index f4fa71d256..20a9896cb7 100644
--- a/phpgwapi/inc/class.groupdav.inc.php
+++ b/phpgwapi/inc/class.groupdav.inc.php
@@ -377,10 +377,10 @@ class groupdav extends HTTP_WebDAV_Server
echo '