Adapt date/time handling to recent changes in libkolabxml; forward attachment parts when saving a Kolab object in a new message

This commit is contained in:
Thomas B 2012-03-08 10:21:21 +01:00
parent 83fe5ad8f5
commit 80fa73b895
4 changed files with 111 additions and 30 deletions

View file

@ -46,7 +46,7 @@ class rcube_kolab_contacts extends rcube_addressbook
'department' => array('limit' => 1),
'email' => array('subtypes' => null),
'phone' => array(),
'address' => array('subtypes' => array('home','business')),
'address' => array('subtypes' => array('home','work')),
'officelocation' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'limit' => 1,
'label' => 'kolab_addressbook.officelocation', 'category' => 'main'),
'website' => array('subtypes' => null),
@ -1046,8 +1046,10 @@ class rcube_kolab_contacts extends rcube_addressbook
}
// photo is stored as separate attachment
if ($record['photo'] && ($att = $record['_attachments'][$record['photo']])) {
$out['photo'] = $att['content'] ? $att['content'] : $this->storagefolder->get_attachment($record['uid'], $att['key']);
if ($record['photo'] && strlen($record['photo']) < 255 && ($att = $record['_attachments'][$record['photo']])) {
// only fetch photo content if requested
if ($rcmail = rcmail::get_instance()->action == 'photo')
$record['photo'] = $att['content'] ? $att['content'] : $this->storagefolder->get_attachment($record['uid'], $att['key']);
}
// remove empty fields
@ -1112,6 +1114,10 @@ class rcube_kolab_contacts extends rcube_addressbook
);
$contact['photo'] = $attkey;
}
else if (isset($contact['photo']) && empty($contact['photo'])) {
// unset photo attachment
$contact['_attachments']['photo.attachment'] = false;
}
return $contact;
}

View file

@ -53,25 +53,25 @@ abstract class kolab_format
}
/**
* Convert the given date/time value into a c_DateTime object
* Convert the given date/time value into a cDateTime object
*
* @param mixed Date/Time value either as unix timestamp, date string or PHP DateTime object
* @param DateTimeZone The timezone the date/time is in. Use global default if empty
* @param boolean True of the given date has no time component
* @return c_DateTime The libkolabxml date/time object or null on error
* @return object The libkolabxml date/time object or null on error
*/
public static function getDateTime($datetime, $tz = null, $dateonly = false)
public static function get_datetime($datetime, $tz = null, $dateonly = false)
{
if (!$tz) $tz = self::$timezone;
$result = null;
if (is_numeric($datetime))
$datetime = new DateTime('@'.$datetime, $tz);
else if (is_string($datetime))
else if (is_string($datetime) && strlen($datetime))
$datetime = new DateTime($datetime, $tz);
if (is_a($datetime, 'DateTime')) {
$result = new KolabDateTime();
$result = new cDateTime();
$result->setDate($datetime->format('Y'), $datetime->format('n'), $datetime->format('j'));
if (!$dateonly)
@ -83,6 +83,41 @@ abstract class kolab_format
return $result;
}
/**
* Convert the given cDateTime into a PHP DateTime object
*
* @param object cDateTime The libkolabxml datetime object
* @return object DateTime PHP datetime instance
*/
public static function php_datetime($cdt)
{
if (!is_object($cdt) || !$cdt->isValid())
return null;
$d = new DateTime;
$d->setTimezone(self::$timezone);
try {
if ($tzs = $cdt->timezone()) {
$tz = new DateTimeZone($tzs);
$d->setTimezone($tz);
}
}
catch (Exception $e) { }
$d->setDate($cdt->year(), $cdt->month(), $cdt->day());
if ($cdt->isDateOnly()) {
$d->_dateonly = true;
$d->setTime(12, 0, 0); // set time to noon to avoid timezone troubles
}
else {
$d->setTime($cdt->hour(), $cdt->minute(), $cdt->second());
}
return $d;
}
/**
* Convert a libkolabxml vector to a PHP array
*

View file

@ -55,6 +55,7 @@ class kolab_format_contact extends kolab_format
'body' => 'notes',
'pgp-publickey' => 'pgppublickey',
'free-busy-url' => 'freebusyurl',
'picture' => 'photo',
);
private $kolab2_phonetypes = array(
'home1' => 'home',
@ -114,7 +115,7 @@ class kolab_format_contact extends kolab_format
if (false && !$this->obj->created()) {
if (!empty($object['created']))
$object['created'] = new DateTime('now', self::$timezone);
$this->obj->setCreated(self::getDateTime($object['created']));
$this->obj->setCreated(self::get_datetime($object['created']));
}
// do the hard work of setting object values
@ -196,10 +197,10 @@ class kolab_format_contact extends kolab_format
$this->obj->setNote($object['notes']);
if ($object['freebusyurl'])
$this->obj->setFreeBusyUrl($object['freebusyurl']);
// if ($object['birthday'])
// $this->obj->setBDay(self::getDateTime($object['birthday'], null, true));
// if ($object['anniversary'])
// $this->obj->setAnniversary(self::getDateTime($object['anniversary'], null, true));
if ($object['birthday'])
$this->obj->setBDay(self::get_datetime($object['birthday'], null, true));
if ($object['anniversary'])
$this->obj->setAnniversary(self::get_datetime($object['anniversary'], null, true));
// handle spouse, children, profession, initials, pgppublickey, etc.
@ -282,6 +283,12 @@ class kolab_format_contact extends kolab_format
$object['notes'] = $this->obj->note();
$object['freebusyurl'] = $this->obj->freeBusyUrl();
if ($bday = self::php_datetime($this->obj->bDay()))
$object['birthday'] = $bday->format('c');
if ($anniversary = self::php_datetime($this->obj->anniversary()))
$object['anniversary'] = $anniversary->format('c');
if ($g = $this->obj->gender())
$object['gender'] = $g == Contact::Female ? 'female' : 'male';
@ -327,11 +334,6 @@ class kolab_format_contact extends kolab_format
}
}
// photo is stored as separate attachment
if ($record['picture'] && ($att = $record['_attachments'][$record['picture']])) {
$object['photo'] = $att['content'] ? $att['content'] : $this->contactstorage->getAttachment($att['key']);
}
// remove empty fields
$this->data = array_filter($object);
}

View file

@ -202,16 +202,19 @@ class kolab_storage_folder
* Fetch a Kolab object attachment which is stored in a separate part
* of the mail MIME message that represents the Kolab record.
*
* @param string Object's UID
* @param string The attachment key stored in the Kolab XML
* @return mixed The attachment content as binary string
* @param string Object's UID
* @param string The attachment's mime number
* @param string IMAP folder where message is stored;
* If set, that also implies that the given UID is an IMAP UID
* @return mixed The attachment content as binary string
*/
public function get_attachment($uid, $key)
public function get_attachment($uid, $part, $mailbox = null)
{
// TODO: implement this
if ($msguid = ($mailbox ? $uid : $this->uid2msguid($uid))) {
if ($mailbox)
$this->imap->set_folder($mailbox);
if ($msguid = $this->uid2msguid($uid)) {
$message = new rcube_message($msguid);
return $this->imap->get_message_part($msguid, $part);
}
return null;
@ -219,21 +222,34 @@ class kolab_storage_folder
/**
* Fetch the mime message from the storage server and extract
* the Kolab groupware object from it
*
* @param string The IMAP message UID to fetch
* @param string The object type expected
* @return array Hash array representing the Kolab object
*/
private function read_object($msguid, $type = null)
private function read_object($msguid, $type = null, $folder = null)
{
if (!$type) $type = $this->type;
if (!$folder) $folder = $this->name;
$ctype= self::KTYPE_PREFIX . $type;
$this->imap->set_folder($this->name);
$this->imap->set_folder($folder);
$message = new rcube_message($msguid);
$attachments = array();
// get XML part
foreach ((array)$message->attachments as $part) {
if ($part->mimetype == $ctype || preg_match('!application/([a-z]+\+)?xml!', $part->mimetype)) {
if (!$xml && ($part->mimetype == $ctype || preg_match('!application/([a-z]+\+)?xml!', $part->mimetype))) {
$xml = $part->body ? $part->body : $message->get_part_content($part->mime_id);
break;
}
else if ($part->filename) {
$attachments[$part->filename] = array(
'key' => $part->mime_id,
'type' => $part->mimetype,
'size' => $part->size,
);
}
}
@ -271,6 +287,7 @@ class kolab_storage_folder
$object = $format->to_array();
$object['_msguid'] = $msguid;
$object['_mailbox'] = $this->name;
$object['_attachments'] = $attachments;
return $object;
}
@ -291,6 +308,15 @@ class kolab_storage_folder
if (!$type)
$type = $this->type;
// copy attachments from old message
if (!empty($object['_msguid']) && ($old = $this->read_object($object['_msguid'], $type, $object['_mailbox']))) {
foreach ($old['_attachments'] as $name => $att) {
if (!isset($object['_attachments'][$name])) {
$object['_attachments'][$name] = $old['_attachments'][$name];
}
}
}
if ($raw_msg = $this->build_message($object, $type)) {
$result = $this->imap->save_message($this->name, $raw_msg, '', false);
@ -410,6 +436,18 @@ class kolab_storage_folder
'', RCMAIL_CHARSET
);
// save object attachments as separate parts
// TODO: optimize memory consumption by using tempfiles for transfer
foreach ((array)$object['_attachments'] as $name => $att) {
if (empty($att['content']) && !empty($att['key'])) {
$msguid = !empty($object['_msguid']) ? $object['_msguid'] : $object['uid'];
$att['content'] = $this->get_attachment($msguid, $att['key'], $object['_mailbox']);
}
if (!empty($att['content'])) {
$mime->addAttachment($att['content'], $att['type'], $name, false);
}
}
return $mime->getMessage();
}