mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-26 00:29:38 +01:00
- merged SyncML-1.2 branch with trunk:
svn merge ^/trunk/infolog@27329 ^/branches/SyncML-1.2/infolog . - completly reverted changes in inc/class.boinfolog.inc.php, as they are not related to SyncML at all: svn revert inc/class.boinfolog.inc.php
This commit is contained in:
parent
d333605510
commit
036b2cd14e
@ -4,6 +4,7 @@
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @author Joerg Lehrke <jlehrke@noc.de>
|
||||
* @package infolog
|
||||
* @copyright (c) 2003-8 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
@ -154,7 +155,7 @@ class infolog_bo
|
||||
'billed' => 'billed', // --> DONE
|
||||
'template' => 'template', // --> cancelled
|
||||
'nonactive' => 'nonactive', // --> cancelled
|
||||
'archive' => 'archive' ), // --> cancelled
|
||||
'archive' => 'archive' ), // --> cancelled
|
||||
'phone' => array(
|
||||
'not-started' => 'call', // iCal NEEDS-ACTION
|
||||
'ongoing' => 'will-call', // iCal IN-PROCESS
|
||||
@ -513,7 +514,6 @@ class infolog_bo
|
||||
$GLOBALS['egw']->contenthistory->updateTimeStamp('infolog_'.$info['info_type'], $info_id, 'delete', time());
|
||||
|
||||
// send email notifications and do the history logging
|
||||
require_once(EGW_INCLUDE_ROOT.'/infolog/inc/class.infolog_tracking.inc.php');
|
||||
if (!is_object($this->tracking))
|
||||
{
|
||||
$this->tracking = new infolog_tracking($this);
|
||||
@ -533,7 +533,7 @@ class infolog_bo
|
||||
* @param boolean $touch_modified=true touch the modification data and sets the modiefier's user-id
|
||||
* @return int/boolean info_id on a successfull write or false
|
||||
*/
|
||||
function write(&$values,$check_defaults=True,$touch_modified=True)
|
||||
function write(&$values, $check_defaults=True, $touch_modified=True)
|
||||
{
|
||||
//echo "boinfolog::write()values="; _debug_array($values);
|
||||
if ($status_only = $values['info_id'] && !$this->check_access($values['info_id'],EGW_ACL_EDIT))
|
||||
@ -578,7 +578,7 @@ class infolog_bo
|
||||
if ($set_completed)
|
||||
{
|
||||
$values['info_datecompleted'] = $this->user_time_now;
|
||||
$values['info_percent'] = '100%';
|
||||
$values['info_percent'] = 100;
|
||||
$forcestatus = true;
|
||||
$status = 'done';
|
||||
if (isset($values['info_type']) && !in_array($values['info_status'],array('done','billed','cancelled'))) {
|
||||
@ -608,7 +608,7 @@ class infolog_bo
|
||||
}
|
||||
if (in_array($values['info_status'],array('done','billed')))
|
||||
{
|
||||
$values['info_percent'] = '100';
|
||||
$values['info_percent'] = 100;
|
||||
}
|
||||
if ((int)$values['info_percent'] == 100 && !in_array($values['info_status'],array('done','billed','cancelled')))
|
||||
{
|
||||
@ -659,7 +659,7 @@ class infolog_bo
|
||||
// Should only an entry be updated which includes the original modification date?
|
||||
// Used in the web-GUI to check against a modification by an other user while editing the entry.
|
||||
// It's now disabled for xmlrpc, as otherwise the xmlrpc code need to be changed!
|
||||
$xmprpc = is_object($GLOBALS['server']) && $GLOBALS['server']->last_method;
|
||||
$xmlrpc = is_object($GLOBALS['server']) && $GLOBALS['server']->last_method;
|
||||
$check_modified = $values['info_datemodified'] && !$xmlrpc ? $values['info_datemodified']-$this->tz_offset_s : false;
|
||||
$values['info_datemodified'] = $this->user_time_now;
|
||||
}
|
||||
@ -1080,7 +1080,7 @@ class infolog_bo
|
||||
$cat_id = $this->categories->name2id($cat_name, 'X-');
|
||||
if (!$cat_id)
|
||||
{
|
||||
$cat_id = $this->categories->add(array('name' => $cat_name,'descr' => $cat_name));
|
||||
$cat_id = $this->categories->add(array('name' => $cat_name, 'descr' => $cat_name, 'access' => 'private'));
|
||||
}
|
||||
|
||||
if ($cat_id)
|
||||
@ -1172,32 +1172,32 @@ class infolog_bo
|
||||
// check if we already send a notification for that infolog entry, eg. starting and due on same day
|
||||
if (in_array($info['info_id'],$notified_info_ids)) continue;
|
||||
|
||||
if (is_null($tracking) || $tracking->user != $user)
|
||||
if (is_null($this->tracking) || $this->tracking->user != $user)
|
||||
{
|
||||
require_once(EGW_INCLUDE_ROOT.'/infolog/inc/class.infolog_tracking.inc.php');
|
||||
$tracking = new infolog_tracking($this);
|
||||
$this->tracking = new infolog_tracking($this);
|
||||
}
|
||||
switch($pref)
|
||||
{
|
||||
case 'notify_due_responsible':
|
||||
$info['message'] = lang('%1 you are responsible for is due at %2',$this->enums['type'][$info['info_type']],
|
||||
$tracking->datetime($info['info_enddate']-$this->tz_offset_s,false));
|
||||
$this->tracking->datetime($info['info_enddate']-$this->tz_offset_s,false));
|
||||
break;
|
||||
case 'notify_due_delegated':
|
||||
$info['message'] = lang('%1 you delegated is due at %2',$this->enums['type'][$info['info_type']],
|
||||
$tracking->datetime($info['info_enddate']-$this->tz_offset_s,false));
|
||||
$this->tracking->datetime($info['info_enddate']-$this->tz_offset_s,false));
|
||||
break;
|
||||
case 'notify_start_responsible':
|
||||
$info['message'] = lang('%1 you are responsible for is starting at %2',$this->enums['type'][$info['info_type']],
|
||||
$tracking->datetime($info['info_startdate']-$this->tz_offset_s,null));
|
||||
$this->tracking->datetime($info['info_startdate']-$this->tz_offset_s,null));
|
||||
break;
|
||||
case 'notify_start_delegated':
|
||||
$info['message'] = lang('%1 you delegated is starting at %2',$this->enums['type'][$info['info_type']],
|
||||
$tracking->datetime($info['info_startdate']-$this->tz_offset_s,null));
|
||||
$this->tracking->datetime($info['info_startdate']-$this->tz_offset_s,null));
|
||||
break;
|
||||
}
|
||||
error_log("notifiying $user($email) about $info[info_subject]: $info[message]");
|
||||
$tracking->send_notification($info,null,$email,$user,$pref);
|
||||
$this->tracking->send_notification($info,null,$email,$user,$pref);
|
||||
|
||||
$notified_info_ids[] = $info['info_id'];
|
||||
}
|
||||
@ -1221,6 +1221,8 @@ class infolog_bo
|
||||
'template' => 'CANCELLED',
|
||||
'nonactive' => 'CANCELLED',
|
||||
'archive' => 'CANCELLED',
|
||||
'deferred' => 'NEEDS-ACTION',
|
||||
'waiting' => 'IN-PROCESS',
|
||||
);
|
||||
|
||||
/** conversion of vtodo status to infolog status
|
||||
@ -1229,7 +1231,9 @@ class infolog_bo
|
||||
*/
|
||||
var $_vtodo2status = array(
|
||||
'NEEDS-ACTION' => 'not-started',
|
||||
'NEEDS ACTION' => 'not-started',
|
||||
'IN-PROCESS' => 'ongoing',
|
||||
'IN PROCESS' => 'ongoing',
|
||||
'COMPLETED' => 'done',
|
||||
'CANCELLED' => 'cancelled',
|
||||
);
|
||||
@ -1285,4 +1289,128 @@ class infolog_bo
|
||||
}
|
||||
return 'ongoing';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Parent ID of an InfoLog entry
|
||||
*
|
||||
* @param string $_guid
|
||||
* @return string parentID
|
||||
*/
|
||||
function getParentID($_guid)
|
||||
{
|
||||
#Horde::logMessage("getParentID($_guid)", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
|
||||
$parentID = False;
|
||||
$myfilter = array('col_filter' => array('info_uid'=>$_guid)) ;
|
||||
if ($_guid && ($found=$this->search($myfilter)) && ($uidmatch = array_shift($found))) {
|
||||
$parentID = $uidmatch['info_id'];
|
||||
};
|
||||
return $parentID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find a matching db entry
|
||||
*
|
||||
* @param array $egwData the vTODO data we try to find
|
||||
* @param boolean $relax=false if asked to relax, we only match against some key fields
|
||||
* @return the infolog_id of the matching entry or false (if none matches)
|
||||
*/
|
||||
function findVTODO($egwData, $relax=false)
|
||||
{
|
||||
$myfilter = array('col_filter' => array('info_uid'=>$egwData['info_uid'])) ;
|
||||
if ($egwData['info_uid']
|
||||
&& ($found = $this->search($myfilter))
|
||||
&& ($uidmatch = array_shift($found)))
|
||||
{
|
||||
return $uidmatch['info_id'];
|
||||
};
|
||||
unset($egwData['info_uid']);
|
||||
|
||||
$filter = array();
|
||||
|
||||
$description = '';
|
||||
if (!empty($egwData['info_des'])) {
|
||||
$description = trim(preg_replace("/\r?\n?\\[[A-Z_]+:.*\\]/i", '', $egwData['info_des']));
|
||||
unset($egwData['info_des']);
|
||||
// Avoid quotation problems
|
||||
$description = preg_replace("/[^\x20-\x7F].*/", '', $description);
|
||||
if (strlen($description)) {
|
||||
$filter['search'] = $description;
|
||||
}
|
||||
}
|
||||
|
||||
if ($egwData['info_id']
|
||||
&& ($found = $this->read($egwData['info_id'])))
|
||||
{
|
||||
// We only do a simple consistency check
|
||||
if ($found['info_subject'] == $egwData['info_subject']
|
||||
&& strpos($found['info_des'], $description) === 0)
|
||||
{
|
||||
return $found['info_id'];
|
||||
}
|
||||
}
|
||||
unset($egwData['info_id']);
|
||||
|
||||
// priority does not need to match
|
||||
unset($egwData['info_priority']);
|
||||
|
||||
$filter['col_filter'] = $egwData;
|
||||
|
||||
if($foundItems = $this->search($filter)) {
|
||||
if(count($foundItems) > 0) {
|
||||
$itemIDs = array_keys($foundItems);
|
||||
return $itemIDs[0];
|
||||
}
|
||||
}
|
||||
|
||||
$filter = array();
|
||||
|
||||
if (!$relax && strlen($description)) {
|
||||
$filter['search'] = $description;
|
||||
}
|
||||
|
||||
$filter['col_filter'] = $egwData;
|
||||
|
||||
// search for date only match
|
||||
unset($filter['col_filter']['info_startdate']);
|
||||
unset($filter['col_filter']['info_datecompleted']);
|
||||
|
||||
// try tasks without category
|
||||
unset($filter['col_filter']['info_cat']);
|
||||
|
||||
#Horde::logMessage("findVTODO Filter\n"
|
||||
# . print_r($filter, true),
|
||||
# __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
foreach ($this->search($filter) as $itemID => $taskData) {
|
||||
# Horde::logMessage("findVTODO Trying\n"
|
||||
# . print_r($taskData, true),
|
||||
# __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
if (isset($egwData['info_cat'])
|
||||
&& isset($taskData['info_cat']) && $taskData['info_cat']
|
||||
&& $egwData['info_cat'] != $taskData['info_cat']) continue;
|
||||
if (isset($egwData['info_startdate'])
|
||||
&& isset($taskData['info_startdate']) && $taskData['info_startdate']) {
|
||||
$parts = @getdate($taskData['info_startdate']);
|
||||
$startdate = @mktime(0, 0, 0, $parts['mon'], $parts['mday'], $parts['year']);
|
||||
if ($egwData['info_startdate'] != $startdate) continue;
|
||||
}
|
||||
// some clients don't support DTSTART
|
||||
if (isset($egwData['info_startdate'])
|
||||
&& (!isset($taskData['info_startdate']) || !$taskData['info_startdate'])
|
||||
&& !$relax) continue;
|
||||
if (isset($egwData['info_datecompleted'])
|
||||
&& isset($taskData['info_datecompleted']) && $taskData['info_datecompleted']) {
|
||||
$parts = @getdate($taskData['info_datecompleted']);
|
||||
$enddate = @mktime(0, 0, 0, $parts['mon'], $parts['mday'], $parts['year']);
|
||||
if ($egwData['info_datecompleted'] != $enddate) continue;
|
||||
}
|
||||
if ((isset($egwData['info_datecompleted'])
|
||||
&& (!isset($taskData['info_datecompleted']) || !$taskData['info_datecompleted'])) ||
|
||||
(!isset($egwData['info_datecompleted'])
|
||||
&& isset($taskData['info_datecompleted']) && $taskData['info_datecompleted'])
|
||||
&& !$relax) continue;
|
||||
return($itemID);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -331,6 +331,7 @@ class infolog_hooks
|
||||
private static function all_cats()
|
||||
{
|
||||
$categories = new categories('','infolog');
|
||||
$accountId = $GLOBALS['egw_info']['user']['account_id'];
|
||||
|
||||
foreach((array)$categories->return_sorted_array(0,False,'','','',true) as $cat)
|
||||
{
|
||||
@ -340,6 +341,14 @@ class infolog_hooks
|
||||
{
|
||||
$s .= ' ♦';
|
||||
}
|
||||
elseif ($cat['owner'] != $accountId)
|
||||
{
|
||||
$s .= '<' . $GLOBALS['egw']->accounts->id2name($cat['owner'], 'account_fullname') . '>';
|
||||
}
|
||||
elseif ($cat['access'] == 'private')
|
||||
{
|
||||
$s .= ' ♥';
|
||||
}
|
||||
$sel_options[$cat['id']] = $s; // 0.9.14 only
|
||||
}
|
||||
return $sel_options;
|
||||
|
@ -4,15 +4,14 @@
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Lars Kneschke <lkneschke@egroupware.org>
|
||||
* @author Joerg Lehrke <jlehrke@noc.de>
|
||||
* @package infolog
|
||||
* @subpackage syncml
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
require_once EGW_API_INC.'/horde/Horde/iCalendar.php';
|
||||
require_once EGW_API_INC.'/horde/Horde/iCalendar/vnote.php';
|
||||
require_once EGW_API_INC.'/horde/Horde/iCalendar/vtodo.php';
|
||||
require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
|
||||
|
||||
/**
|
||||
* InfoLog: Create and parse iCal's
|
||||
@ -20,17 +19,24 @@ require_once EGW_API_INC.'/horde/Horde/iCalendar/vtodo.php';
|
||||
*/
|
||||
class infolog_ical extends infolog_bo
|
||||
{
|
||||
/**
|
||||
* @var array conversion of the priority egw => ical
|
||||
*/
|
||||
var $egw_priority2vcal_priority = array(
|
||||
0 => 3,
|
||||
1 => 2,
|
||||
2 => 1,
|
||||
3 => 1,
|
||||
0 => 9, // low
|
||||
1 => 5, // normal
|
||||
2 => 3, // high
|
||||
3 => 1, // urgent
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array conversion of the priority ical => egw
|
||||
*/
|
||||
var $vcal_priority2egw_priority = array(
|
||||
1 => 2,
|
||||
2 => 1,
|
||||
3 => 0,
|
||||
9 => 0, 8 => 0, 7 => 0, // low
|
||||
6 => 1, 5 => 1, 4 => 1, 0 => 1, // normal
|
||||
3 => 2, 2 => 2, // high
|
||||
1 => 3, // urgent
|
||||
);
|
||||
|
||||
/**
|
||||
@ -41,6 +47,32 @@ class infolog_ical extends infolog_bo
|
||||
var $productManufacturer = 'file';
|
||||
var $productName = '';
|
||||
|
||||
/**
|
||||
* Shall we use the UID extensions of the description field?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
var $uidExtension = false;
|
||||
|
||||
/**
|
||||
* Client CTCap Properties
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $clientProperties;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $_clientProperties client properties
|
||||
*/
|
||||
function __construct(&$_clientProperties = array())
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->clientProperties = $_clientProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports one InfoLog tast to an iCalendar VTODO
|
||||
*
|
||||
@ -53,9 +85,36 @@ class infolog_ical extends infolog_bo
|
||||
{
|
||||
$taskData = $this->read($_taskID);
|
||||
|
||||
$taskData = $GLOBALS['egw']->translation->convert($taskData, $GLOBALS['egw']->translation->charset(), 'UTF-8');
|
||||
if ($taskData['info_id_parent'])
|
||||
{
|
||||
$parent = $this->read($taskData['info_id_parent']);
|
||||
$taskData['info_id_parent'] = $parent['info_uid'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$taskData['info_id_parent'] = '';
|
||||
}
|
||||
|
||||
$taskGUID = $GLOBALS['egw']->common->generate_uid('infolog_task',$_taskID);
|
||||
if ($this->uidExtension)
|
||||
{
|
||||
if (!preg_match('/\[UID:.+\]/m', $taskData['info_des']))
|
||||
{
|
||||
$taskData['info_des'] .= "\n[UID:" . $taskData['info_uid'] . "]";
|
||||
if ($taskData['info_id_parent'] != '')
|
||||
{
|
||||
$taskData['info_des'] .= "\n[PARENT_UID:" . $taskData['info_id_parent'] . "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($taskData['info_cat']))
|
||||
{
|
||||
$cats = $this->get_categories(array($taskData['info_cat']));
|
||||
$taskData['info_cat'] = $cats[0];
|
||||
}
|
||||
|
||||
$taskData = $GLOBALS['egw']->translation->convert($taskData,
|
||||
$GLOBALS['egw']->translation->charset(), 'UTF-8');
|
||||
|
||||
$vcal = new Horde_iCalendar;
|
||||
$vcal->setAttribute('VERSION',$_version);
|
||||
@ -63,35 +122,91 @@ class infolog_ical extends infolog_bo
|
||||
|
||||
$vevent = Horde_iCalendar::newComponent('VTODO',$vcal);
|
||||
|
||||
// set fields that may contain non-ascii chars and encode them if necessary
|
||||
foreach(array(
|
||||
'SUMMARY' => $taskData['info_subject'],
|
||||
'DESCRIPTION' => $taskData['info_des'],
|
||||
'LOCATION' => $taskData['info_location'],
|
||||
) as $field => $value)
|
||||
if (!isset($this->clientProperties['SUMMARY']['Size']))
|
||||
{
|
||||
$vevent->setAttribute($field,$value);
|
||||
$options = array();
|
||||
if($this->productManufacturer != 'GroupDAV' && preg_match('/([\000-\012\015\016\020-\037\075])/',$value))
|
||||
// make SUMMARY a required field
|
||||
$this->clientProperties['SUMMARY']['Size'] = 0xFFFF;
|
||||
$this->clientProperties['SUMMARY']['NoTruncate'] = false;
|
||||
}
|
||||
// set fields that may contain non-ascii chars and encode them if necessary
|
||||
foreach (array(
|
||||
'SUMMARY' => $taskData['info_subject'],
|
||||
'DESCRIPTION' => $taskData['info_des'],
|
||||
'LOCATION' => $taskData['info_location'],
|
||||
'RELATED-TO' => $taskData['info_id_parent'],
|
||||
'UID' => $taskData['info_uid'],
|
||||
'CATEGORIES' => $taskData['info_cat'],
|
||||
) as $field => $value)
|
||||
{
|
||||
if (isset($this->clientProperties[$field]['Size']))
|
||||
{
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
$size = $this->clientProperties[$field]['Size'];
|
||||
$noTruncate = $this->clientProperties[$field]['NoTruncate'];
|
||||
#Horde::logMessage("VTODO $field Size: $size, NoTruncate: " .
|
||||
# ($noTruncate ? 'TRUE' : 'FALSE'), __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
}
|
||||
if($this->productManufacturer != 'GroupDAV' && preg_match('/([\177-\377])/',$value))
|
||||
else
|
||||
{
|
||||
$size = -1;
|
||||
$noTruncate = false;
|
||||
}
|
||||
$cursize = strlen($value);
|
||||
if (($size > 0) && $cursize > $size)
|
||||
{
|
||||
if ($noTruncate)
|
||||
{
|
||||
Horde::logMessage("VTODO $field omitted due to maximum size $size",
|
||||
__FILE__, __LINE__, PEAR_LOG_WARNING);
|
||||
continue; // skip field
|
||||
}
|
||||
// truncate the value to size
|
||||
$value = substr($value, 0, $size -1);
|
||||
#Horde::logMessage("VTODO $field truncated to maximum size $size",
|
||||
# __FILE__, __LINE__, PEAR_LOG_INFO);
|
||||
}
|
||||
|
||||
if (empty($value) && ($size < 0 || $noTruncate)) continue;
|
||||
|
||||
if ($field == 'RELATED-TO')
|
||||
{
|
||||
$options = array('RELTYPE' => 'PARENT');
|
||||
}
|
||||
else
|
||||
{
|
||||
$options = array();
|
||||
}
|
||||
|
||||
/*if(preg_match('/([\000-\012\015\016\020-\037\075])/', $value)) {
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}*/
|
||||
if ($this->productManufacturer != 'groupdav'
|
||||
&& preg_match('/([\177-\377])/',$value))
|
||||
{
|
||||
$options['CHARSET'] = 'UTF-8';
|
||||
}
|
||||
if ($options) $vevent->setParameter($field, $options);
|
||||
$vevent->setAttribute($field, $value, $options);
|
||||
}
|
||||
if($taskData['info_startdate'])
|
||||
|
||||
if ($taskData['info_startdate'])
|
||||
{
|
||||
$vevent->setAttribute('DTSTART',$taskData['info_startdate']);
|
||||
if($taskData['info_enddate'])
|
||||
$vevent->setAttribute('DUE',$taskData['info_enddate']);
|
||||
if($taskData['info_datecompleted'])
|
||||
}
|
||||
|
||||
if ($taskData['info_enddate'])
|
||||
{
|
||||
$parts = @getdate($taskData['info_enddate']);
|
||||
$value = @mktime(12, 0, 0, $parts['mon'], $parts['mday'], $parts['year']);
|
||||
$vevent->setAttribute('DUE', $value);
|
||||
}
|
||||
|
||||
if ($taskData['info_datecompleted'])
|
||||
{
|
||||
$vevent->setAttribute('COMPLETED',$taskData['info_datecompleted']);
|
||||
}
|
||||
|
||||
$vevent->setAttribute('DTSTAMP',time());
|
||||
$vevent->setAttribute('CREATED',$GLOBALS['egw']->contenthistory->getTSforAction('infolog_task',$_taskID,'add'));
|
||||
$vevent->setAttribute('LAST-MODIFIED',$GLOBALS['egw']->contenthistory->getTSforAction('infolog_task',$_taskID,'modify'));
|
||||
$vevent->setAttribute('UID',$taskData['info_uid']);
|
||||
$vevent->setAttribute('CLASS',$taskData['info_access'] == 'public' ? 'PUBLIC' : 'PRIVATE');
|
||||
$vevent->setAttribute('STATUS',$this->status2vtodo($taskData['info_status']));
|
||||
// we try to preserv the original infolog status as X-INFOLOG-STATUS, so we can restore it, if the user does not modify STATUS
|
||||
@ -99,16 +214,12 @@ class infolog_ical extends infolog_bo
|
||||
$vevent->setAttribute('PERCENT-COMPLETE',$taskData['info_percent']);
|
||||
$vevent->setAttribute('PRIORITY',$this->egw_priority2vcal_priority[$taskData['info_priority']]);
|
||||
|
||||
if (!empty($taskData['info_cat']))
|
||||
{
|
||||
$cats = $this->get_categories(array($taskData['info_cat']));
|
||||
$vevent->setAttribute('CATEGORIES', $cats[0]);
|
||||
}
|
||||
//error_log("\n\nexportvcal\n". print_r($vcal,true));
|
||||
//error_log("\n\nexportvcal\n". print_r($vevent,true));
|
||||
|
||||
$vcal->addComponent($vevent);
|
||||
error_log("\n\nexportvcal from infolog\n");
|
||||
return $vcal->exportvCalendar();
|
||||
|
||||
$retval = $vcal->exportvCalendar();
|
||||
Horde::logMessage("exportVTODO:\n" . print_r($retval, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,104 +227,143 @@ class infolog_ical extends infolog_bo
|
||||
*
|
||||
* @param string $_vcalData
|
||||
* @param int $_taskID=-1 info_id, default -1 = new entry
|
||||
* @param boolean $merge=false merge data with existing entry
|
||||
* @return int|boolean integer info_id or false on error
|
||||
*/
|
||||
function importVTODO(&$_vcalData, $_taskID=-1)
|
||||
function importVTODO(&$_vcalData, $_taskID=-1, $merge=false)
|
||||
{
|
||||
if(!$taskData = $this->vtodotoegw($_vcalData,$_taskID))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!$taskData = $this->vtodotoegw($_vcalData,$_taskID)) return false;
|
||||
|
||||
// we suppose that a not set status in a vtodo means that the task did not started yet
|
||||
if(empty($taskData['info_status']))
|
||||
if (empty($taskData['info_status']))
|
||||
{
|
||||
$taskData['info_status'] = 'not-started';
|
||||
}
|
||||
|
||||
if (empty($taskData['info_datecompleted']))
|
||||
{
|
||||
$taskData['info_datecompleted'] = 0;
|
||||
}
|
||||
|
||||
return $this->write($taskData);
|
||||
}
|
||||
|
||||
function searchVTODO($_vcalData, $contentID=null)
|
||||
{
|
||||
if(!$egwData = $this->vtodotoegw($_vcalData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$myfilter = array('col_filter' => array('info_uid'=>$egwData['info_uid'])) ;
|
||||
if ($egwData['info_uid'] && ($found=parent::search($myfilter)) && ($uidmatch = array_shift($found)))
|
||||
/**
|
||||
* Search a matching infolog entry for the VTODO data
|
||||
*
|
||||
* @param string $_vcalData VTODO
|
||||
* @param int $contentID=null infolog_id (or null, if unkown)
|
||||
* @param boolean $relax=false if true, a weaker match algorithm is used
|
||||
* @return infolog_id of a matching entry or false, if nothing was found
|
||||
*/
|
||||
function searchVTODO($_vcalData, $contentID=null, $relax=false) {
|
||||
$result = false;
|
||||
|
||||
if (($egwData = $this->vtodotoegw($_vcalData)))
|
||||
{
|
||||
return $uidmatch['info_id'];
|
||||
};
|
||||
unset($egwData['info_uid']);
|
||||
|
||||
if ($contentID) {
|
||||
$egwData['info_id'] = $contentID;
|
||||
}
|
||||
|
||||
#unset($egwData['info_priority']);
|
||||
|
||||
$filter = array('col_filter' => $egwData);
|
||||
if($foundItems = $this->search($filter)) {
|
||||
if(count($foundItems) > 0) {
|
||||
$itemIDs = array_keys($foundItems);
|
||||
return $itemIDs[0];
|
||||
if ($contentID)
|
||||
{
|
||||
$egwData['info_id'] = $contentID;
|
||||
}
|
||||
$result = $this->findVTODO($egwData, $relax);
|
||||
}
|
||||
|
||||
return false;
|
||||
return $result;
|
||||
}
|
||||
|
||||
function vtodotoegw($_vcalData,$_taskID=-1)
|
||||
/**
|
||||
* Convert VTODO into a eGW infolog entry
|
||||
*
|
||||
* @param string $_vcalData VTODO data
|
||||
* @param int $_taskID=-1 infolog_id of the entry
|
||||
* @return array infolog entry or false on error
|
||||
*/
|
||||
function vtodotoegw($_vcalData, $_taskID=-1)
|
||||
{
|
||||
$vcal = new Horde_iCalendar;
|
||||
if(!$vcal->parsevCalendar($_vcalData))
|
||||
if (!($vcal->parsevCalendar($_vcalData))) return false;
|
||||
|
||||
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length']))
|
||||
{
|
||||
return FALSE;
|
||||
$minimum_uid_length = $GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$minimum_uid_length = 8;
|
||||
}
|
||||
|
||||
$components = $vcal->getComponents();
|
||||
|
||||
if(count($components) > 0)
|
||||
foreach ($components as $component)
|
||||
{
|
||||
$component = $components[0];
|
||||
if(is_a($component, 'Horde_iCalendar_vtodo'))
|
||||
if (is_a($component, 'Horde_iCalendar_vtodo'))
|
||||
{
|
||||
$taskData = array();
|
||||
if($_taskID > 0)
|
||||
$taskData['info_type'] = 'task';
|
||||
|
||||
if ($_taskID > 0)
|
||||
{
|
||||
$taskData['info_id'] = $_taskID;
|
||||
}
|
||||
foreach($component->_attributes as $attributes)
|
||||
foreach ($component->_attributes as $attributes)
|
||||
{
|
||||
switch($attributes['name'])
|
||||
//$attributes['value'] = trim($attributes['value']);
|
||||
if (empty($attributes['value'])) continue;
|
||||
switch ($attributes['name'])
|
||||
{
|
||||
case 'CLASS':
|
||||
$taskData['info_access'] = strtolower($attributes['value']);
|
||||
$taskData['info_access'] = strtolower($attributes['value']);
|
||||
break;
|
||||
|
||||
case 'DESCRIPTION':
|
||||
$taskData['info_des'] = $attributes['value'];
|
||||
$value = $attributes['value'];
|
||||
if (preg_match('/\s*\[UID:(.+)?\]/Usm', $value, $matches))
|
||||
{
|
||||
if (!isset($taskData['info_uid'])
|
||||
&& strlen($matches[1]) >= $minimum_uid_length)
|
||||
{
|
||||
$taskData['info_uid'] = $matches[1];
|
||||
}
|
||||
//$value = str_replace($matches[0], '', $value);
|
||||
}
|
||||
if (preg_match('/\s*\[PARENT_UID:(.+)?\]/Usm', $value, $matches))
|
||||
{
|
||||
if (!isset($taskData['info_id_parent'])
|
||||
&& strlen($matches[1]) >= $minimum_uid_length)
|
||||
{
|
||||
$taskData['info_id_parent'] = $this->getParentID($matches[1]);
|
||||
}
|
||||
//$value = str_replace($matches[0], '', $value);
|
||||
}
|
||||
$taskData['info_des'] = $value;
|
||||
break;
|
||||
|
||||
case 'LOCATION':
|
||||
$taskData['info_location'] = $attributes['value'];
|
||||
$taskData['info_location'] = $attributes['value'];
|
||||
break;
|
||||
|
||||
case 'DUE':
|
||||
$taskData['info_enddate'] = $attributes['value'];
|
||||
// eGroupWare uses date only
|
||||
$parts = @getdate($attributes['value']);
|
||||
$value = @mktime(0, 0, 0, $parts['mon'], $parts['mday'], $parts['year']);
|
||||
$taskData['info_enddate'] = $value;
|
||||
break;
|
||||
|
||||
case 'COMPLETED':
|
||||
$taskData['info_datecompleted'] = $attributes['value'];
|
||||
break;
|
||||
|
||||
case 'DTSTART':
|
||||
$taskData['info_startdate'] = $attributes['value'];
|
||||
$taskData['info_startdate'] = $attributes['value'];
|
||||
break;
|
||||
|
||||
case 'PRIORITY':
|
||||
if (1 <= $attributes['value'] && $attributes['value'] <= 3)
|
||||
{
|
||||
$taskData['info_priority'] = $this->vcal_priority2egw_priority[$attributes['value']];
|
||||
}
|
||||
else
|
||||
{
|
||||
$taskData['info_priority'] = 1; // default = normal
|
||||
if (1 <= $attributes['value'] && $attributes['value'] <= 3) {
|
||||
$taskData['info_priority'] = $this->vcal_priority2egw_priority[$attributes['value']];
|
||||
} else {
|
||||
$taskData['info_priority'] = 1; // default = normal
|
||||
}
|
||||
break;
|
||||
|
||||
case 'STATUS':
|
||||
// check if we (still) have X-INFOLOG-STATUS set AND it would give an unchanged status (no change by the user)
|
||||
foreach($component->_attributes as $attr)
|
||||
@ -223,28 +373,26 @@ class infolog_ical extends infolog_bo
|
||||
$taskData['info_status'] = $this->vtodo2status($attributes['value'],
|
||||
$attr['name'] == 'X-INFOLOG-STATUS' ? $attr['value'] : null);
|
||||
break;
|
||||
|
||||
case 'SUMMARY':
|
||||
$taskData['info_subject'] = $attributes['value'];
|
||||
$taskData['info_subject'] = $attributes['value'];
|
||||
break;
|
||||
|
||||
case 'RELATED-TO':
|
||||
$taskData['info_id_parent'] = $this->getParentID($attributes['value']);
|
||||
break;
|
||||
|
||||
case 'CATEGORIES':
|
||||
$cats = $this->find_or_add_categories(explode(',', $attributes['value']));
|
||||
$taskData['info_cat'] = $cats[0];
|
||||
break;
|
||||
|
||||
case 'UID':
|
||||
$taskData['info_uid'] = $attributes['value'];
|
||||
if ($_taskID <= 0 && !empty($attributes['value']) && ($uid_task = $this->read($attributes['value'])))
|
||||
{
|
||||
$taskData['info_id'] = $uid_task['id'];
|
||||
unset($uid_task);
|
||||
if (strlen($attributes['value']) >= $minimum_uid_length) {
|
||||
$taskData['info_uid'] = $attributes['value'];
|
||||
}
|
||||
// not use weak uids that might come from syncml clients
|
||||
if (isset($event['uid']) && (strlen($event['uid']) < 20 || is_numeric($event['uid'])))
|
||||
{
|
||||
unset ($event['uid']);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'PERCENT-COMPLETE':
|
||||
$taskData['info_percent'] = (int) $attributes['value'];
|
||||
break;
|
||||
@ -254,18 +402,28 @@ class infolog_ical extends infolog_bo
|
||||
# do NOT convert here
|
||||
#$taskData = $GLOBALS['egw']->translation->convert($taskData, 'UTF-8');
|
||||
|
||||
Horde::logMessage("vtodotoegw:\n" . print_r($taskData, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
|
||||
return $taskData;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export an infolog entry as VNOTE
|
||||
*
|
||||
* @param int $_noteID the infolog_id of the entry
|
||||
* @param string $_type content type (e.g. text/plain)
|
||||
* @return string VNOTE representation of the infolog entry
|
||||
*/
|
||||
function exportVNOTE($_noteID, $_type)
|
||||
{
|
||||
$note = $this->read($_noteID);
|
||||
$note = $GLOBALS['egw']->translation->convert($note, $GLOBALS['egw']->translation->charset(), 'UTF-8');
|
||||
$note = $GLOBALS['egw']->translation->convert($note,
|
||||
$GLOBALS['egw']->translation->charset(), 'UTF-8');
|
||||
|
||||
switch($_type)
|
||||
switch ($_type)
|
||||
{
|
||||
case 'text/plain':
|
||||
$txt = $note['info_subject']."\n\n".$note['info_des'];
|
||||
@ -273,66 +431,101 @@ class infolog_ical extends infolog_bo
|
||||
break;
|
||||
|
||||
case 'text/x-vnote':
|
||||
$noteGUID = $GLOBALS['egw']->common->generate_uid('infolog_note',$_noteID);
|
||||
$vnote = new Horde_iCalendar_vnote();
|
||||
$options = array('CHARSET' => 'UTF-8');
|
||||
$vNote->setAttribute('VERSION', '1.1');
|
||||
$vnote->setAttribute('SUMMARY',$note['info_subject']);
|
||||
$vnote->setAttribute('BODY',$note['info_des']);
|
||||
if($note['info_startdate'])
|
||||
foreach (array( 'SUMMARY' => $note['info_subject'],
|
||||
'BODY' => $note['info_des'],
|
||||
) as $field => $value)
|
||||
{
|
||||
$vnote->setAttribute($field, $value);
|
||||
if ($this->productManufacturer != 'groupdav'
|
||||
&& preg_match('/([\177-\377])/', $value))
|
||||
{
|
||||
$vevent->setParameter($field, $options);
|
||||
}
|
||||
}
|
||||
if ($note['info_startdate'])
|
||||
{
|
||||
$vnote->setAttribute('DCREATED',$note['info_startdate']);
|
||||
}
|
||||
$vnote->setAttribute('DCREATED',$GLOBALS['egw']->contenthistory->getTSforAction('infolog_note',$_noteID,'add'));
|
||||
$vnote->setAttribute('LAST-MODIFIED',$GLOBALS['egw']->contenthistory->getTSforAction('infolog_note',$_noteID,'modify'));
|
||||
|
||||
if (!empty($note['info_cat']))
|
||||
{
|
||||
$cats = $this->get_categories(array($note['info_cat']));
|
||||
$vnote->setAttribute('CATEGORIES', $cats[0]);
|
||||
$value = $cats[0];
|
||||
$vnote->setAttribute('CATEGORIES', $value);
|
||||
if ($this->productManufacturer != 'groupdav'
|
||||
&& preg_match('/([\177-\377])/', $value))
|
||||
{
|
||||
$vevent->setParameter('CATEGORIES', $options);
|
||||
}
|
||||
}
|
||||
|
||||
#$vnote->setAttribute('UID',$noteGUID);
|
||||
#$vnote->setAttribute('CLASS',$taskData['info_access'] == 'public' ? 'PUBLIC' : 'PRIVATE');
|
||||
|
||||
#$options = array('CHARSET' => 'UTF-8','ENCODING' => 'QUOTED-PRINTABLE');
|
||||
#$vnote->setParameter('SUMMARY', $options);
|
||||
#$vnote->setParameter('DESCRIPTION', $options);
|
||||
|
||||
return $vnote->exportvCalendar();
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function importVNOTE(&$_vcalData, $_type, $_noteID = -1)
|
||||
/**
|
||||
* Import a VNOTE component of an iCal
|
||||
*
|
||||
* @param string $_vcalData
|
||||
* @param string $_type content type (eg.g text/plain)
|
||||
* @param int $_taskID=-1 info_id, default -1 = new entry
|
||||
* @param boolean $merge=false merge data with existing entry
|
||||
* @return int|boolean integer info_id or false on error
|
||||
*/
|
||||
function importVNOTE(&$_vcalData, $_type, $_noteID = -1, $merge=false)
|
||||
{
|
||||
if(!$note = $this->vnotetoegw($_vcalData, $_type))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!($note = $this->vnotetoegw($_vcalData, $_type))) return false;
|
||||
|
||||
if($_noteID > 0)
|
||||
{
|
||||
$note['info_id'] = $_noteID;
|
||||
}
|
||||
if($_noteID > 0) $note['info_id'] = $_noteID;
|
||||
|
||||
if(empty($note['info_status'])) {
|
||||
$note['info_status'] = 'done';
|
||||
}
|
||||
if (empty($note['info_status'])) $note['info_status'] = 'done';
|
||||
|
||||
#_debug_array($taskData);exit;
|
||||
return $this->write($note);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search a matching infolog entry for the VNOTE data
|
||||
*
|
||||
* @param string $_vcalData VNOTE
|
||||
* @param int $contentID=null infolog_id (or null, if unkown)
|
||||
* @return infolog_id of a matching entry or false, if nothing was found
|
||||
*/
|
||||
function searchVNOTE($_vcalData, $_type, $contentID=null)
|
||||
{
|
||||
if(!$note = $this->vnotetoegw($_vcalData,$_type)) {
|
||||
return false;
|
||||
}
|
||||
if ($contentID) {
|
||||
$note['info_id'] = $contentID;
|
||||
if (!($note = $this->vnotetoegw($_vcalData,$_type))) return false;
|
||||
|
||||
if ($contentID) $note['info_id'] = $contentID;
|
||||
|
||||
unset($note['info_startdate']);
|
||||
|
||||
$filter = array();
|
||||
|
||||
if (!empty($note['info_des']))
|
||||
{
|
||||
$description = trim(preg_replace("/\r?\n?\\[[A-Z_]+:.*\\]/i", '', $note['info_des']));
|
||||
unset($note['info_des']);
|
||||
if (strlen($description))
|
||||
{
|
||||
$filter['search'] = $description;
|
||||
}
|
||||
}
|
||||
|
||||
$filter = array('col_filter' => $note);
|
||||
if($foundItems = $this->search($filter)) {
|
||||
if(count($foundItems) > 0) {
|
||||
$filter['col_filter'] = $note;
|
||||
|
||||
if (($foundItems = $this->search($filter)))
|
||||
{
|
||||
if (count($foundItems) > 0)
|
||||
{
|
||||
$itemIDs = array_keys($foundItems);
|
||||
return $itemIDs[0];
|
||||
}
|
||||
@ -341,9 +534,16 @@ class infolog_ical extends infolog_bo
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert VTODO into a eGW infolog entry
|
||||
*
|
||||
* @param string $_data VNOTE data
|
||||
* @param string $_type content type (eg.g text/plain)
|
||||
* @return array infolog entry or false on error
|
||||
*/
|
||||
function vnotetoegw($_data, $_type)
|
||||
{
|
||||
switch($_type)
|
||||
switch ($_type)
|
||||
{
|
||||
case 'text/plain':
|
||||
$note = array();
|
||||
@ -360,7 +560,7 @@ class infolog_ical extends infolog_bo
|
||||
else
|
||||
{
|
||||
// should better be imported as subject, but causes duplicates
|
||||
// TODO: should be qexamined
|
||||
// TODO: should be examined
|
||||
$note['info_des'] = $txt;
|
||||
}
|
||||
|
||||
@ -369,34 +569,31 @@ class infolog_ical extends infolog_bo
|
||||
|
||||
case 'text/x-vnote':
|
||||
$vnote = new Horde_iCalendar;
|
||||
if (!$vcal->parsevCalendar($_data))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!$vcal->parsevCalendar($_data)) return false;
|
||||
|
||||
$components = $vnote->getComponent();
|
||||
if(count($components) > 0)
|
||||
foreach ($components as $component)
|
||||
{
|
||||
$component = $components[0];
|
||||
if(is_a($component, 'Horde_iCalendar_vnote'))
|
||||
if (is_a($component, 'Horde_iCalendar_vnote'))
|
||||
{
|
||||
$note = array();
|
||||
$note['info_type'] = 'note';
|
||||
|
||||
foreach($component->_attributes as $attribute)
|
||||
foreach ($component->_attributes as $attribute)
|
||||
{
|
||||
switch ($attribute['name'])
|
||||
{
|
||||
case 'BODY':
|
||||
$note['info_des'] = $attribute['value'];
|
||||
break;
|
||||
|
||||
case 'SUMMARY':
|
||||
$note['info_subject'] = $attribute['value'];
|
||||
break;
|
||||
|
||||
case 'CATEGORIES':
|
||||
{
|
||||
$cats = $this->find_or_add_categories(explode(',', $attribute['value']));
|
||||
$note['info_cat'] = $cats[0];
|
||||
}
|
||||
$cats = $this->find_or_add_categories(explode(',', $attribute['value']));
|
||||
$note['info_cat'] = $cats[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -404,7 +601,7 @@ class infolog_ical extends infolog_bo
|
||||
return $note;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -415,11 +612,41 @@ class infolog_ical extends infolog_bo
|
||||
* @param string $_productManufacturer
|
||||
* @param string $_productName
|
||||
*/
|
||||
function setSupportedFields($_productManufacturer='file', $_productName='')
|
||||
function setSupportedFields($_productManufacturer='', $_productName='')
|
||||
{
|
||||
// save them vor later use
|
||||
$this->productManufacturer = $_productManufacturer;
|
||||
$this->productName = $_productName;
|
||||
$state = &$_SESSION['SyncML.state'];
|
||||
if (isset($state))
|
||||
{
|
||||
$deviceInfo = $state->getClientDeviceInfo();
|
||||
}
|
||||
|
||||
// store product manufacturer and name, to be able to use it elsewhere
|
||||
if ($_productManufacturer)
|
||||
{
|
||||
$this->productManufacturer = strtolower($_productManufacturer);
|
||||
$this->productName = strtolower($_productName);
|
||||
}
|
||||
|
||||
if (isset($deviceInfo) && is_array($deviceInfo))
|
||||
{
|
||||
if (!isset($this->productManufacturer)
|
||||
|| $this->productManufacturer == ''
|
||||
|| $this->productManufacturer == 'file')
|
||||
{
|
||||
$this->productManufacturer = strtolower($deviceInfo['manufacturer']);
|
||||
}
|
||||
if (!isset($this->productName) || $this->productName == '')
|
||||
{
|
||||
$this->productName = strtolower($deviceInfo['model']);
|
||||
}
|
||||
if (isset($deviceInfo['uidExtension'])
|
||||
&& $deviceInfo['uidExtension'])
|
||||
{
|
||||
$this->uidExtension = true;
|
||||
}
|
||||
}
|
||||
|
||||
Horde::logMessage('setSupportedFields(' . $this->productManufacturer . ', ' . $this->productName .')', __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,13 +4,14 @@
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Lars Kneschke <lkneschke@egroupware.org>
|
||||
* @author Joerg Lehrke <jlehrke@noc.de>
|
||||
* @package infolog
|
||||
* @subpackage syncml
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
require_once EGW_API_INC.'/horde/Horde/iCalendar.php';
|
||||
require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
|
||||
|
||||
/**
|
||||
* InfoLog: Create and parse SIF
|
||||
@ -38,58 +39,88 @@ class infolog_sif extends infolog_bo
|
||||
|
||||
// mappings for SIFTask to InfologTask
|
||||
var $_sifTaskMapping = array(
|
||||
'ActualWork' => '',
|
||||
'ActualWork' => '',
|
||||
'BillingInformation' => '',
|
||||
'Body' => 'info_des',
|
||||
'Categories' => 'info_cat',
|
||||
'Companies' => '',
|
||||
'Complete' => '',
|
||||
'DateCompleted' => 'info_datecompleted',
|
||||
'DueDate' => 'info_enddate',
|
||||
'Importance' => 'info_priority',
|
||||
'IsRecurring' => '',
|
||||
'Mileage' => '',
|
||||
'PercentComplete' => 'info_percent',
|
||||
'ReminderSet' => '',
|
||||
'ReminderTime' => '',
|
||||
'Sensitivity' => 'info_access',
|
||||
'StartDate' => 'info_startdate',
|
||||
'Status' => 'info_status',
|
||||
'Subject' => 'info_subject',
|
||||
'TeamTask' => '',
|
||||
'TotalWork' => '',
|
||||
'RecurrenceType' => '',
|
||||
'Interval' => '',
|
||||
'MonthOfYear' => '',
|
||||
'DayOfMonth' => '',
|
||||
'DayOfWeekMask' => '',
|
||||
'Instance' => '',
|
||||
'PatternStartDate' => '',
|
||||
'NoEndDate' => '',
|
||||
'PatternEndDate' => '',
|
||||
'Occurrences' => '',
|
||||
'Body' => 'info_des',
|
||||
'Categories' => 'info_cat',
|
||||
'Companies' => '',
|
||||
'Complete' => 'complete',
|
||||
'DateCompleted' => 'info_datecompleted',
|
||||
'DueDate' => 'info_enddate',
|
||||
'Importance' => 'info_priority',
|
||||
'IsRecurring' => '',
|
||||
'Mileage' => '',
|
||||
'PercentComplete' => 'info_percent',
|
||||
'ReminderSet' => '',
|
||||
'ReminderTime' => '',
|
||||
'Sensitivity' => 'info_access',
|
||||
'StartDate' => 'info_startdate',
|
||||
'Status' => 'info_status',
|
||||
'Subject' => 'info_subject',
|
||||
'TeamTask' => '',
|
||||
'TotalWork' => '',
|
||||
'RecurrenceType' => '',
|
||||
'Interval' => '',
|
||||
'MonthOfYear' => '',
|
||||
'DayOfMonth' => '',
|
||||
'DayOfWeekMask' => '',
|
||||
'Instance' => '',
|
||||
'PatternStartDate' => '',
|
||||
'NoEndDate' => '',
|
||||
'PatternEndDate' => '',
|
||||
'Occurrences' => '',
|
||||
);
|
||||
|
||||
// standard headers
|
||||
const xml_decl = '<?xml version="1.0" encoding="UTF-8"?>';
|
||||
const SIF_decl = '<SIFVersion>1.1</SIFVersion>';
|
||||
|
||||
/**
|
||||
* name and version of the sync-client
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $productName = 'mozilla plugin';
|
||||
var $productSoftwareVersion = '0.3';
|
||||
|
||||
/**
|
||||
* Shall we use the UID extensions of the description field?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
var $uidExtension = false;
|
||||
|
||||
|
||||
function startElement($_parser, $_tag, $_attributes) {
|
||||
function startElement($_parser, $_tag, $_attributes)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
function endElement($_parser, $_tag) {
|
||||
error_log("infolog: tag=$_tag data=".trim($this->sifData));
|
||||
if(!empty($this->_currentSIFMapping[$_tag])) {
|
||||
function endElement($_parser, $_tag)
|
||||
{
|
||||
#error_log("infolog: tag=$_tag data=".trim($this->sifData));
|
||||
if (!empty($this->_currentSIFMapping[$_tag]))
|
||||
{
|
||||
$this->_extractedSIFData[$this->_currentSIFMapping[$_tag]] = trim($this->sifData);
|
||||
}
|
||||
unset($this->sifData);
|
||||
}
|
||||
|
||||
function characterData($_parser, $_data) {
|
||||
function characterData($_parser, $_data)
|
||||
{
|
||||
$this->sifData .= $_data;
|
||||
}
|
||||
|
||||
function siftoegw($_sifData, $_sifType) {
|
||||
/**
|
||||
* Convert SIF data into a eGW infolog entry
|
||||
*
|
||||
* @param string $sifData the SIF data
|
||||
* @param string $_sifType type (note/task)
|
||||
* @return array infolog entry or false on error
|
||||
*/
|
||||
function siftoegw($sifData, $_sifType)
|
||||
{
|
||||
$sysCharSet = $GLOBALS['egw']->translation->charset();
|
||||
$sifData = base64_decode($_sifData);
|
||||
|
||||
#$tmpfname = tempnam('/tmp/sync/contents','sift_');
|
||||
|
||||
@ -115,29 +146,44 @@ class infolog_sif extends infolog_bo
|
||||
xml_set_element_handler($this->xml_parser, "startElement", "endElement");
|
||||
xml_set_character_data_handler($this->xml_parser, "characterData");
|
||||
$this->strXmlData = xml_parse($this->xml_parser, $sifData);
|
||||
if(!$this->strXmlData) {
|
||||
|
||||
if (!$this->strXmlData)
|
||||
{
|
||||
error_log(sprintf("XML error: %s at line %d",
|
||||
xml_error_string(xml_get_error_code($this->xml_parser)),
|
||||
xml_get_current_line_number($this->xml_parser)));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!array($this->_extractedSIFData)) {
|
||||
return false;
|
||||
}
|
||||
if (!array($this->_extractedSIFData)) return false;
|
||||
|
||||
switch($_sifType) {
|
||||
switch ($_sifType)
|
||||
{
|
||||
case 'task':
|
||||
$taskData = array();
|
||||
$vcal = new Horde_iCalendar;
|
||||
|
||||
$taskData['info_type'] = 'task';
|
||||
$taskData['info_status'] = 'not-started';
|
||||
|
||||
foreach($this->_extractedSIFData as $key => $value) {
|
||||
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length']))
|
||||
{
|
||||
$minimum_uid_length = $GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$minimum_uid_length = 8;
|
||||
}
|
||||
|
||||
foreach ($this->_extractedSIFData as $key => $value)
|
||||
{
|
||||
$value = preg_replace('/<\!\[CDATA\[(.+)\]\]>/Usim', '$1', $value);
|
||||
$value = $GLOBALS['egw']->translation->convert($value, 'utf-8', $sysCharSet);
|
||||
error_log("infolog key=$key => value=$value");
|
||||
#error_log("infolog key=$key => value=$value");
|
||||
if (empty($value)) continue;
|
||||
|
||||
switch($key) {
|
||||
switch($key)
|
||||
{
|
||||
case 'info_access':
|
||||
$taskData[$key] = ((int)$value > 0) ? 'private' : 'public';
|
||||
break;
|
||||
@ -145,19 +191,18 @@ class infolog_sif extends infolog_bo
|
||||
case 'info_datecompleted':
|
||||
case 'info_enddate':
|
||||
case 'info_startdate':
|
||||
if(!empty($value)) {
|
||||
if (!empty($value))
|
||||
{
|
||||
$taskData[$key] = $vcal->_parseDateTime($value);
|
||||
// somehow the client always deliver a timestamp about 3538 seconds, when no startdate set.
|
||||
if($taskData[$key] < 10000)
|
||||
$taskData[$key] = '';
|
||||
} else {
|
||||
$taskData[$key] = '';
|
||||
if ($taskData[$key] < 10000) unset($taskData[$key]);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'info_cat':
|
||||
if (!empty($value)) {
|
||||
if (!empty($value))
|
||||
{
|
||||
$categories = $this->find_or_add_categories(explode(';', $value));
|
||||
$taskData['info_cat'] = $categories[0];
|
||||
}
|
||||
@ -168,8 +213,8 @@ class infolog_sif extends infolog_bo
|
||||
break;
|
||||
|
||||
case 'info_status':
|
||||
$taskData[$key] = ((int)$value == 2) ? 'done' : 'ongoing';
|
||||
switch($value) {
|
||||
switch ($value)
|
||||
{
|
||||
case '0':
|
||||
$taskData[$key] = 'not-started';
|
||||
break;
|
||||
@ -178,9 +223,20 @@ class infolog_sif extends infolog_bo
|
||||
break;
|
||||
case '2':
|
||||
$taskData[$key] = 'done';
|
||||
$taskData['info_percent'] = 100;
|
||||
break;
|
||||
case '3':
|
||||
$taskData[$key] = 'waiting';
|
||||
break;
|
||||
case '4':
|
||||
$taskData[$key] = 'cancelled';
|
||||
if ($this->productName == 'blackberry plug-in')
|
||||
{
|
||||
$taskData[$key] = 'deferred';
|
||||
}
|
||||
else
|
||||
{
|
||||
$taskData[$key] = 'cancelled';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$taskData[$key] = 'ongoing';
|
||||
@ -188,11 +244,35 @@ class infolog_sif extends infolog_bo
|
||||
}
|
||||
break;
|
||||
|
||||
case 'complete':
|
||||
$taskData['info_status'] = 'done';
|
||||
$taskData['info_percent'] = 100;
|
||||
break;
|
||||
|
||||
case 'info_des':
|
||||
// extract our UID and PARENT_UID information
|
||||
if (preg_match('/\s*\[UID:(.+)?\]/Usm', $value, $matches))
|
||||
{
|
||||
if (strlen($matches[1]) >= $minimum_uid_length)
|
||||
{
|
||||
$taskData['info_uid'] = $matches[1];
|
||||
}
|
||||
//$value = str_replace($matches[0], '', $value);
|
||||
}
|
||||
if (preg_match('/\s*\[PARENT_UID:(.+)?\]/Usm', $value, $matches))
|
||||
{
|
||||
if (strlen($matches[1]) >= $minimum_uid_length)
|
||||
{
|
||||
$taskData['info_id_parent'] = $this->getParentID($matches[1]);
|
||||
}
|
||||
//$value = str_replace($matches[0], '', $value);
|
||||
}
|
||||
|
||||
default:
|
||||
$taskData[$key] = $value;
|
||||
break;
|
||||
}
|
||||
error_log("infolog task key=$key => value=".$taskData[$key]);
|
||||
#error_log("infolog task key=$key => value=" . $taskData[$key]);
|
||||
}
|
||||
|
||||
return $taskData;
|
||||
@ -203,28 +283,32 @@ class infolog_sif extends infolog_bo
|
||||
$noteData['info_type'] = 'note';
|
||||
$vcal = new Horde_iCalendar;
|
||||
|
||||
foreach($this->_extractedSIFData as $key => $value)
|
||||
foreach ($this->_extractedSIFData as $key => $value)
|
||||
{
|
||||
$value = preg_replace('/<\!\[CDATA\[(.+)\]\]>/Usim', '$1', $value);
|
||||
$value = $GLOBALS['egw']->translation->convert($value, 'utf-8', $sysCharSet);
|
||||
|
||||
error_log("infolog client key=$key => value=".$value);
|
||||
#error_log("infolog client key=$key => value=" . $value);
|
||||
switch ($key)
|
||||
{
|
||||
case 'info_startdate':
|
||||
if(!empty($value)) {
|
||||
if (!empty($value))
|
||||
{
|
||||
$noteData[$key] = $vcal->_parseDateTime($value);
|
||||
// somehow the client always deliver a timestamp about 3538 seconds, when no startdate set.
|
||||
if($noteData[$key] < 10000)
|
||||
$noteData[$key] = '';
|
||||
} else {
|
||||
if ($noteData[$key] < 10000) $noteData[$key] = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$noteData[$key] = '';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'info_cat':
|
||||
if (!empty($value)) {
|
||||
if (!empty($value))
|
||||
{
|
||||
$categories = $this->find_or_add_categories(explode(';', $value));
|
||||
$taskData['info_cat'] = $categories[0];
|
||||
$noteData['info_cat'] = $categories[0];
|
||||
}
|
||||
break;
|
||||
|
||||
@ -232,7 +316,7 @@ class infolog_sif extends infolog_bo
|
||||
$noteData[$key] = $value;
|
||||
break;
|
||||
}
|
||||
error_log("infolog note key=$key => value=".$noteData[$key]);
|
||||
#error_log("infolog note key=$key => value=".$noteData[$key]);
|
||||
}
|
||||
return $noteData;
|
||||
break;
|
||||
@ -243,17 +327,33 @@ class infolog_sif extends infolog_bo
|
||||
}
|
||||
}
|
||||
|
||||
function searchSIF($_sifData, $_sifType, $contentID=null) {
|
||||
if(!$egwData = $this->siftoegw($_sifData, $_sifType)) {
|
||||
return false;
|
||||
}
|
||||
if ($contentID) {
|
||||
$egwData['info_id'] = $contentID;
|
||||
}
|
||||
/**
|
||||
* Search for SIF data a matching infolog entry
|
||||
*
|
||||
* @param string $sifData the SIF data
|
||||
* @param string $_sifType type (note/task)
|
||||
* @param int $contentID=null infolog_id (or null, if unkown)
|
||||
* @param boolean $relax=false if true, a weaker match algorithm is used
|
||||
* @return infolog_id of a matching entry or false, if nothing was found
|
||||
*/
|
||||
function searchSIF($_sifData, $_sifType, $contentID=null, $relax=false)
|
||||
{
|
||||
if (!($egwData = $this->siftoegw($_sifData, $_sifType))) return false;
|
||||
|
||||
$filter = array('col_filter' => $egwData);
|
||||
if($foundItems = $this->search($filter)) {
|
||||
if(count($foundItems) > 0) {
|
||||
if ($contentID) $egwData['info_id'] = $contentID;
|
||||
|
||||
if ($_sifType == 'task') return $this->findVTODO($egwData, $relax);
|
||||
|
||||
if ($_sifType == 'note') unset($egwData['info_startdate']);
|
||||
|
||||
$filter = array();
|
||||
|
||||
$filter['col_filter'] = $egwData;
|
||||
|
||||
if ($foundItems = $this->search($filter))
|
||||
{
|
||||
if (count($foundItems) > 0)
|
||||
{
|
||||
$itemIDs = array_keys($foundItems);
|
||||
return $itemIDs[0];
|
||||
}
|
||||
@ -262,46 +362,119 @@ class infolog_sif extends infolog_bo
|
||||
return false;
|
||||
}
|
||||
|
||||
function addSIF($_sifData, $_id, $_sifType) {
|
||||
if(!$egwData = $this->siftoegw($_sifData, $_sifType)) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Add SIF data entry
|
||||
*
|
||||
* @param string $sifData the SIF data
|
||||
* @param string $_sifType type (note/task)
|
||||
* @param boolean $merge=false reserved for future use
|
||||
* @return infolog_id of the new entry or false, for errors
|
||||
*/
|
||||
function addSIF($_sifData, $_id, $_sifType, $merge=false)
|
||||
{
|
||||
if (!($egwData = $this->siftoegw($_sifData, $_sifType))) return false;
|
||||
|
||||
if($_id > 0)
|
||||
$egwData['info_id'] = $_id;
|
||||
if ($_id > 0) $egwData['info_id'] = $_id;
|
||||
|
||||
if (empty($taskData['info_datecompleted']))
|
||||
{
|
||||
$taskData['info_datecompleted'] = 0;
|
||||
}
|
||||
|
||||
$egwID = $this->write($egwData, false);
|
||||
|
||||
return $egwID;
|
||||
}
|
||||
|
||||
function getSIF($_id, $_sifType) {
|
||||
switch($_sifType) {
|
||||
|
||||
/**
|
||||
* Export an infolog entry as SIF data
|
||||
*
|
||||
* @param int $_id the infolog_id of the entry
|
||||
* @param string $_sifType type (note/task)
|
||||
* @return string SIF representation of the infolog entry
|
||||
*/
|
||||
function getSIF($_id, $_sifType)
|
||||
{
|
||||
$sysCharSet = $GLOBALS['egw']->translation->charset();
|
||||
|
||||
switch($_sifType)
|
||||
{
|
||||
case 'task':
|
||||
if($taskData = $this->read($_id)) {
|
||||
$sysCharSet = $GLOBALS['egw']->translation->charset();
|
||||
$vcal = new Horde_iCalendar;
|
||||
if (($taskData = $this->read($_id)))
|
||||
{
|
||||
$vcal = new Horde_iCalendar('1.0');
|
||||
|
||||
$sifTask = '<task>';
|
||||
|
||||
foreach($this->_sifTaskMapping as $sifField => $egwField)
|
||||
if ($taskData['info_id_parent'])
|
||||
{
|
||||
if(empty($egwField)) continue;
|
||||
$parent = $this->read($taskData['info_id_parent']);
|
||||
$taskData['info_id_parent'] = $parent['info_uid'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$taskData['info_id_parent'] = '';
|
||||
}
|
||||
|
||||
if (!preg_match('/\[UID:.+\]/m', $taskData['info_des']))
|
||||
{
|
||||
$taskData['info_des'] .= "\r\n[UID:" . $taskData['info_uid'] . "]";
|
||||
if ($taskData['info_id_parent'] != '')
|
||||
{
|
||||
$taskData['info_des'] .= "\r\n[PARENT_UID:" . $taskData['info_id_parent'] . "]";
|
||||
}
|
||||
}
|
||||
|
||||
$sifTask = self::xml_decl . "\n<task>" . self::SIF_decl;
|
||||
|
||||
foreach ($this->_sifTaskMapping as $sifField => $egwField)
|
||||
{
|
||||
if (empty($egwField)) continue;
|
||||
|
||||
$value = $GLOBALS['egw']->translation->convert($taskData[$egwField], $sysCharSet, 'utf-8');
|
||||
|
||||
switch($sifField) {
|
||||
switch ($sifField)
|
||||
{
|
||||
|
||||
case 'Complete':
|
||||
// is handled with DateCompleted
|
||||
break;
|
||||
|
||||
case 'DateCompleted':
|
||||
case 'DueDate':
|
||||
case 'StartDate':
|
||||
if(!empty($value)) {
|
||||
$value = $vcal->_exportDateTime($value);
|
||||
if ($taskData[info_status] == 'done')
|
||||
{
|
||||
$sifTask .= "<Complete>1</Complete>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sifTask .= "<DateCompleted></DateCompleted><Complete>0</Complete>";
|
||||
continue;
|
||||
}
|
||||
case 'DueDate':
|
||||
if (!empty($value))
|
||||
{
|
||||
$hdate = new Horde_Date($value);
|
||||
$value = $vcal->_exportDate($hdate, '000000Z');
|
||||
$sifTask .= "<$sifField>$value</$sifField>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sifTask .= "<$sifField></$sifField>";
|
||||
}
|
||||
break;
|
||||
case 'StartDate':
|
||||
if (!empty($value))
|
||||
{
|
||||
$value = $vcal->_exportDateTime($value);
|
||||
$sifTask .= "<$sifField>$value</$sifField>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sifTask .= "<$sifField></$sifField>";
|
||||
}
|
||||
$sifTask .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
|
||||
case 'Importance':
|
||||
if($value > 3) $value = 3;
|
||||
if ($value > 3) $value = 3;
|
||||
$sifTask .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
|
||||
@ -311,20 +484,26 @@ class infolog_sif extends infolog_bo
|
||||
break;
|
||||
|
||||
case 'Status':
|
||||
switch($value) {
|
||||
switch ($value)
|
||||
{
|
||||
case 'cancelled':
|
||||
case 'deferred':
|
||||
$value = '4';
|
||||
break;
|
||||
case 'waiting':
|
||||
case 'nonactive':
|
||||
$value = '3';
|
||||
break;
|
||||
case 'done':
|
||||
case 'archive':
|
||||
case 'billed':
|
||||
$value = '2';
|
||||
break;
|
||||
case 'not-started':
|
||||
case 'template':
|
||||
$value = '0';
|
||||
break;
|
||||
case 'ongoing':
|
||||
$value = '1';
|
||||
break;
|
||||
default:
|
||||
default: //ongoing
|
||||
$value = 1;
|
||||
break;
|
||||
}
|
||||
@ -332,102 +511,69 @@ class infolog_sif extends infolog_bo
|
||||
break;
|
||||
|
||||
case 'Categories':
|
||||
if (!empty($value))
|
||||
if (!empty($value) && $value)
|
||||
{
|
||||
$value = implode('; ', $this->get_categories(array($value)));
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
|
||||
}
|
||||
$sifTask .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
$value = @htmlspecialchars($value, ENT_QUOTES, 'utf-8');
|
||||
$sifTask .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$sifTask .= '<ActualWork>0</ActualWork><IsRecurring>0</IsRecurring>';
|
||||
return base64_encode($sifTask);
|
||||
|
||||
/* return base64_encode("<task>
|
||||
<ActualWork>0</ActualWork>
|
||||
<BillingInformation></BillingInformation>
|
||||
<Body></Body>
|
||||
<Categories></Categories>
|
||||
<Companies></Companies>
|
||||
<Complete>0</Complete>
|
||||
<DateCompleted></DateCompleted>
|
||||
<DueDate></DueDate>
|
||||
<Importance>1</Importance>
|
||||
<IsRecurring>0</IsRecurring>
|
||||
<Mileage></Mileage>
|
||||
<PercentComplete>0</PercentComplete>
|
||||
<ReminderSet>0</ReminderSet>
|
||||
<ReminderTime></ReminderTime>
|
||||
<Sensitivity>0</Sensitivity>
|
||||
<StartDate>45001231T230000Z</StartDate>
|
||||
<Status>3</Status>
|
||||
<Subject>TARAAA3</Subject>
|
||||
<TeamTask>0</TeamTask>
|
||||
<TotalWork>0</TotalWork>
|
||||
<RecurrenceType>1</RecurrenceType>
|
||||
<Interval>1</Interval>
|
||||
<MonthOfYear>0</MonthOfYear>
|
||||
<DayOfMonth>0</DayOfMonth>
|
||||
<DayOfWeekMask>4</DayOfWeekMask>
|
||||
<Instance>0</Instance>
|
||||
<PatternStartDate>20060320T230000Z</PatternStartDate>
|
||||
<NoEndDate>1</NoEndDate>
|
||||
<PatternEndDate></PatternEndDate>
|
||||
<Occurrences>10</Occurrences>
|
||||
</task>
|
||||
"); */
|
||||
$sifTask .= '<ActualWork>0</ActualWork><IsRecurring>0</IsRecurring></task>';
|
||||
return $sifTask;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'note':
|
||||
if($taskData = $this->read($_id)) {
|
||||
$sysCharSet = $GLOBALS['egw']->translation->charset();
|
||||
$vcal = new Horde_iCalendar;
|
||||
if (($taskData = $this->read($_id)))
|
||||
{
|
||||
$vcal = new Horde_iCalendar('1.0');
|
||||
|
||||
$sifNote = '<note>';
|
||||
$sifNote = self::xml_decl . "\n<note>" . self::SIF_decl;
|
||||
|
||||
foreach($this->_sifNoteMapping as $sifField => $egwField)
|
||||
foreach ($this->_sifNoteMapping as $sifField => $egwField)
|
||||
{
|
||||
if(empty($egwField)) continue;
|
||||
|
||||
$value = $GLOBALS['egw']->translation->convert($taskData[$egwField], $sysCharSet, 'utf-8');
|
||||
|
||||
switch($sifField) {
|
||||
switch ($sifField)
|
||||
{
|
||||
case 'Date':
|
||||
if(!empty($value)) {
|
||||
if (!empty($value))
|
||||
{
|
||||
$value = $vcal->_exportDateTime($value);
|
||||
}
|
||||
$sifNote .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
|
||||
case 'Body':
|
||||
$value = $GLOBALS['egw']->translation->convert($taskData['info_subject'], $sysCharSet, 'utf-8') . "\n" . $value;
|
||||
$sifNote .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
|
||||
case 'Categories':
|
||||
if (!empty($value))
|
||||
{
|
||||
$value = implode('; ', $this->get_categories(array($value)));
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
|
||||
}
|
||||
$sifNote .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
$value = @htmlspecialchars($value, ENT_QUOTES, 'utf-8');
|
||||
$sifNote .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return base64_encode($sifNote);
|
||||
$sifNote .= '</note>';
|
||||
return $sifNote;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -437,117 +583,35 @@ class infolog_sif extends infolog_bo
|
||||
|
||||
}
|
||||
|
||||
function exportVTODO($_taskID, $_version)
|
||||
/**
|
||||
* Set the supported fields
|
||||
*
|
||||
* Currently we only store name and version, manucfacturer is always Funambol
|
||||
*
|
||||
* @param string $_productName
|
||||
* @param string $_productSoftwareVersion
|
||||
*/
|
||||
function setSupportedFields($_productName='', $_productSoftwareVersion='')
|
||||
{
|
||||
error_log(__METHOD__."called : $_version ,$_taskID");
|
||||
$taskData = $this->read($_taskID);
|
||||
$state = &$_SESSION['SyncML.state'];
|
||||
$deviceInfo = $state->getClientDeviceInfo();
|
||||
|
||||
$taskData = $GLOBALS['egw']->translation->convert($taskData,$GLOBALS['egw']->translation->charset(),'UTF-8');
|
||||
|
||||
//_debug_array($taskData);
|
||||
|
||||
$taskGUID = $GLOBALS['phpgw']->common->generate_uid('infolog_task',$_taskID);
|
||||
|
||||
$vcal = new Horde_iCalendar;
|
||||
$vcal->setAttribute('VERSION',$_version);
|
||||
$vcal->setAttribute('METHOD','PUBLISH');
|
||||
|
||||
$vevent = Horde_iCalendar::newComponent('VTODO',$vcal);
|
||||
|
||||
$options = array();
|
||||
|
||||
$vevent->setAttribute('SUMMARY',$taskData['info_subject']);
|
||||
$vevent->setAttribute('DESCRIPTION',$taskData['info_des']);
|
||||
if($taskData['info_startdate'])
|
||||
$vevent->setAttribute('DTSTART',$taskData['info_startdate']);
|
||||
if($taskData['info_enddate'])
|
||||
$vevent->setAttribute('DUE',$taskData['info_enddate']);
|
||||
$vevent->setAttribute('DTSTAMP',time());
|
||||
$vevent->setAttribute('CREATED',$GLOBALS['phpgw']->contenthistory->getTSforAction('infolog_task',$_taskID,'add'));
|
||||
$vevent->setAttribute('LAST-MODIFIED',$GLOBALS['phpgw']->contenthistory->getTSforAction('infolog_task',$_taskID,'modify'));
|
||||
$vevent->setAttribute('UID',$taskGUID);
|
||||
$vevent->setAttribute('CLASS',(($taskData['info_access'] == 'public')?'PUBLIC':'PRIVATE'));
|
||||
$vevent->setAttribute('STATUS',(($taskData['info_status'] == 'completed')?'COMPLETED':'NEEDS-ACTION'));
|
||||
// 3=urgent => 1, 2=high => 2, 1=normal => 3, 0=low => 4
|
||||
$vevent->setAttribute('PRIORITY',4-$taskData['info_priority']);
|
||||
|
||||
#$vevent->setAttribute('TRANSP','OPAQUE');
|
||||
# status
|
||||
# ATTENDEE
|
||||
|
||||
$options = array('CHARSET' => 'UTF-8','ENCODING' => 'QUOTED-PRINTABLE');
|
||||
$vevent->setParameter('SUMMARY', $options);
|
||||
$vevent->setParameter('DESCRIPTION', $options);
|
||||
|
||||
$vcal->addComponent($vevent);
|
||||
|
||||
#print "<pre>";
|
||||
#print $vcal->exportvCalendar();
|
||||
#print "</pre>";
|
||||
|
||||
return $vcal->exportvCalendar();
|
||||
}
|
||||
|
||||
function importVTODO(&$_vcalData, $_taskID=-1)
|
||||
{
|
||||
$botranslation = CreateObject('phpgwapi.translation');
|
||||
|
||||
$vcal = new Horde_iCalendar;
|
||||
if(!$vcal->parsevCalendar($_vcalData))
|
||||
if (isset($deviceInfo) && is_array($deviceInfo))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
$components = $vcal->getComponents();
|
||||
if(count($components) > 0)
|
||||
{
|
||||
$component = $components[0];
|
||||
if(is_a($component, 'Horde_iCalendar_vtodo'))
|
||||
if (isset($deviceInfo['uidExtension']) &&
|
||||
$deviceInfo['uidExtension'])
|
||||
{
|
||||
if($_taskID>0)
|
||||
$taskData['info_id'] = $_taskID;
|
||||
|
||||
foreach($component->_attributes as $attributes)
|
||||
{
|
||||
#print $attributes['name'].' - '.$attributes['value'].'<br>';
|
||||
#$attributes['value'] = $GLOBALS['egw']->translation->convert($attributes['value'],'UTF-8');
|
||||
switch($attributes['name'])
|
||||
{
|
||||
case 'CLASS':
|
||||
$taskData['info_access'] = strtolower($attributes['value']);
|
||||
break;
|
||||
case 'DESCRIPTION':
|
||||
$taskData['info_des'] = $attributes['value'];
|
||||
break;
|
||||
case 'DUE':
|
||||
$taskData['info_enddate'] = $attributes['value'];
|
||||
break;
|
||||
case 'DTSTART':
|
||||
$taskData['info_startdate'] = $attributes['value'];
|
||||
break;
|
||||
case 'PRIORITY':
|
||||
// 1 => 3=urgent, 2 => 2=high, 3 => 1=normal, 4 => 0=low
|
||||
if (1 <= $attributes['value'] && $attributes['value'] <= 4)
|
||||
{
|
||||
$taskData['info_priority'] = 4 - $attributes['value'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$taskData['info_priority'] = 1; // default = normal
|
||||
}
|
||||
break;
|
||||
case 'STATUS':
|
||||
$taskData['info_status'] = (strtolower($attributes['value']) == 'completed') ? 'done' : 'ongoing';
|
||||
break;
|
||||
case 'SUMMARY':
|
||||
$taskData['info_subject'] = $attributes['value'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
#_debug_array($eventData);exit;
|
||||
return $this->write($taskData);
|
||||
$this->uidExtension = true;
|
||||
}
|
||||
}
|
||||
// store product name and version, to be able to use it elsewhere
|
||||
if ($_productName)
|
||||
{
|
||||
$this->productName = strtolower($_productName);
|
||||
if (preg_match('/^[^\d]*(\d+\.?\d*)[\.|\d]*$/', $_productSoftwareVersion, $matches))
|
||||
{
|
||||
$this->productSoftwareVersion = $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -344,6 +344,12 @@ class infolog_so
|
||||
*/
|
||||
function read($info_id) // did _not_ ensure ACL
|
||||
{
|
||||
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'])) {
|
||||
$minimum_uid_length = $GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'];
|
||||
} else {
|
||||
$minimum_uid_length = 8;
|
||||
}
|
||||
|
||||
//echo "<p>read($info_id) ".function_backtrace()."</p>\n";
|
||||
if ($info_id && ((int)$info_id == $this->data['info_id'] || $info_id == $this->data['info_uid']))
|
||||
{
|
||||
@ -356,6 +362,14 @@ class infolog_so
|
||||
$this->init( );
|
||||
return False;
|
||||
}
|
||||
if (!$this->data['info_uid'] || strlen($this->data['info_uid']) < $minimum_uid_length) {
|
||||
// entry without uid --> create one based on our info_id and save it
|
||||
|
||||
$this->data['info_uid'] = $GLOBALS['egw']->common->generate_uid('infolog', $info_id);
|
||||
$this->db->update($this->info_table,
|
||||
array('info_uid' => $this->data['info_uid']),
|
||||
array('info_id' => $this->data['info_id']), __LINE__,__FILE__);
|
||||
}
|
||||
if (!is_array($this->data['info_responsible']))
|
||||
{
|
||||
$this->data['info_responsible'] = $this->data['info_responsible'] ? explode(',',$this->data['info_responsible']) : array();
|
||||
@ -499,6 +513,12 @@ class infolog_so
|
||||
*/
|
||||
function write($values,$check_modified=0) // did _not_ ensure ACL
|
||||
{
|
||||
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'])) {
|
||||
$minimum_uid_length = $GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'];
|
||||
} else {
|
||||
$minimum_uid_length = 8;
|
||||
}
|
||||
|
||||
//echo "soinfolog::write(,$check_modified) values="; _debug_array($values);
|
||||
$info_id = (int) $values['info_id'];
|
||||
|
||||
@ -540,12 +560,17 @@ class infolog_so
|
||||
$this->db->insert($this->info_table,$to_write,false,__LINE__,__FILE__);
|
||||
$info_id = $this->data['info_id'] = $this->db->get_last_insert_id($this->info_table,'info_id');
|
||||
|
||||
if (!$this->data['info_uid']) // new entry without uid --> create one based on our info_id and save it
|
||||
{
|
||||
$this->data['info_uid'] = $GLOBALS['egw']->common->generate_uid('infolog',$info_id);
|
||||
$this->db->update($this->info_table,array('info_uid'=>$this->data['info_uid']),array('info_id'=>$info_id),__LINE__,__FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->data['info_uid'] || strlen($this->data['info_uid']) < $minimum_uid_length) {
|
||||
// entry without uid --> create one based on our info_id and save it
|
||||
|
||||
$this->data['info_uid'] = $GLOBALS['egw']->common->generate_uid('infolog', $info_id);
|
||||
$this->db->update($this->info_table,
|
||||
array('info_uid' => $this->data['info_uid']),
|
||||
array('info_id' => $info_id), __LINE__,__FILE__);
|
||||
}
|
||||
|
||||
//echo "<p>soinfolog.write values= "; _debug_array($values);
|
||||
|
||||
// write customfields now
|
||||
@ -775,6 +800,7 @@ class infolog_so
|
||||
if ($action == '' || $action == 'sp' || count($links))
|
||||
{
|
||||
$sql_query = "FROM $this->info_table main $join WHERE ($filtermethod $pid $sql_query) $link_extra";
|
||||
#error_log("infolog.so.search:\n" . print_r($sql_query, true));
|
||||
|
||||
if ($this->db->Type == 'mysql' && $this->db->ServerInfo['version'] >= 4.0)
|
||||
{
|
||||
|
@ -186,6 +186,7 @@ class infolog_tracking extends bo_tracking
|
||||
*/
|
||||
function get_details($data)
|
||||
{
|
||||
$header_done = false;
|
||||
$responsible = array();
|
||||
if ($data['info_responsible'])
|
||||
{
|
||||
|
@ -654,6 +654,7 @@ class infolog_ui
|
||||
*
|
||||
* @param int|array $values=0 info_id (default _GET[info_id])
|
||||
* @param string $referer=''
|
||||
* @param boolean $closesingle=false
|
||||
*/
|
||||
function close($values=0,$referer='',$closesingle=false)
|
||||
{
|
||||
@ -973,6 +974,7 @@ class infolog_ui
|
||||
}
|
||||
$parent = $this->bo->so->data;
|
||||
$content['info_id'] = $info_id = 0;
|
||||
$content['info_uid'] = ''; // ensure that we have our own UID
|
||||
$content['info_owner'] = $this->user;
|
||||
$content['info_id_parent'] = $parent['info_id'];
|
||||
/*
|
||||
@ -1432,7 +1434,6 @@ class infolog_ui
|
||||
#continue;
|
||||
}
|
||||
$message .= $bofelamimail->wordwrap($value,75,"\n");
|
||||
#$message .= $bodyAppend;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user