Correctly handle object moving in kolab cache

This commit is contained in:
Thomas B 2012-05-03 10:28:42 +02:00
parent 3fc78aa409
commit c9963d279c
2 changed files with 92 additions and 27 deletions

View file

@ -66,22 +66,8 @@ class kolab_storage_cache
return; return;
} }
// strip namespace prefix from folder name
$ns = $this->folder->get_namespace();
$nsdata = $this->imap->get_namespace($ns);
if (is_array($nsdata[0]) && strpos($this->folder->name, $nsdata[0][0]) === 0) {
$subpath = substr($this->folder->name, strlen($nsdata[0][0]));
if ($ns == 'other') {
list($user, $suffix) = explode($nsdata[0][1], $subpath);
$subpath = $suffix;
}
}
else {
$subpath = $this->folder->name;
}
// compose fully qualified ressource uri for this instance // compose fully qualified ressource uri for this instance
$this->resource_uri = 'imap://' . urlencode($this->folder->get_owner()) . '@' . $this->imap->options['host'] . '/' . $subpath; $this->resource_uri = $this->folder->get_resource_uri();
$this->ready = $this->enabled; $this->ready = $this->enabled;
} }
@ -140,14 +126,22 @@ class kolab_storage_cache
/** /**
* Read a single entry from cache or * Read a single entry from cache or
*
* @param string Related IMAP message UID
* @param string Object type to read
* @param string IMAP folder name the entry relates to
* @param array Hash array with object properties or null if not found
*/ */
public function get($msguid, $type = null, $folder = null) public function get($msguid, $type = null, $foldername = null)
{ {
// delegate to another cache instance
if ($foldername && $foldername != $this->folder->name) {
return kolab_storage::get_folder($foldername)->cache->get($msguid, $object);
}
// load object if not in memory // load object if not in memory
if (!isset($this->objects[$msguid])) { if (!isset($this->objects[$msguid])) {
if ($this->ready) { if ($this->ready) {
// TODO: handle $folder != $this->folder->name situations
$sql_result = $this->db->query( $sql_result = $this->db->query(
"SELECT * FROM kolab_cache ". "SELECT * FROM kolab_cache ".
"WHERE resource=? AND msguid=?", "WHERE resource=? AND msguid=?",
@ -162,7 +156,7 @@ class kolab_storage_cache
// fetch from IMAP if not present in cache // fetch from IMAP if not present in cache
if (empty($this->objects[$msguid])) { if (empty($this->objects[$msguid])) {
$result = $this->_fetch(array($msguid), $type, $folder); $result = $this->_fetch(array($msguid), $type, $foldername);
$this->objects[$msguid] = $result[0]; $this->objects[$msguid] = $result[0];
} }
} }
@ -172,14 +166,22 @@ class kolab_storage_cache
/** /**
* Insert/Update a cache entry
* *
* @param string Related IMAP message UID
* @param mixed Hash array with object properties to save or false to delete the cache entry
* @param string IMAP folder name the entry relates to
*/ */
public function set($msguid, $object, $folder = null) public function set($msguid, $object, $foldername = null)
{ {
// delegate to another cache instance
if ($foldername && $foldername != $this->folder->name) {
kolab_storage::get_folder($foldername)->cache->set($msguid, $object);
return;
}
// write to cache // write to cache
if ($this->ready) { if ($this->ready) {
// TODO: handle $folder != $this->folder->name situations
// remove old entry // remove old entry
$this->db->query("DELETE FROM kolab_cache WHERE resource=? AND msguid=?", $this->db->query("DELETE FROM kolab_cache WHERE resource=? AND msguid=?",
$this->resource_uri, $msguid); $this->resource_uri, $msguid);
@ -219,6 +221,36 @@ class kolab_storage_cache
$this->uid2msg[$object['uid']] = $msguid; $this->uid2msg[$object['uid']] = $msguid;
} }
/**
* Move an existing cache entry to a new resource
*
* @param string Entry's IMAP message UID
* @param string Entry's Object UID
* @param string Target IMAP folder to move it to
*/
public function move($msguid, $objuid, $target_folder)
{
$target = kolab_storage::get_folder($target_folder);
// resolve new message UID in target folder
if ($new_msguid = $target->cache->uid2msguid($objuid)) {
$this->db->query(
"UPDATE kolab_cache SET resource=?, msguid=? ".
"WHERE resource=? AND msguid=?",
$target->get_resource_uri(),
$new_msguid,
$this->resource_uri,
$msguid
);
}
else {
// just clear cache entry
$this->set($msguid, false);
}
unset($this->uid2msg[$uid]);
}
/** /**
* Remove all objects from local cache * Remove all objects from local cache
@ -365,7 +397,7 @@ class kolab_storage_cache
// set type specific values // set type specific values
if ($this->folder->type == 'event') { if ($this->folder->type == 'event') {
// database runs in server's timetone so using date() is safe // database runs in server's timezone so using date() is what we want
$sql_data['dtstart'] = date('Y-m-d H:i:s', is_object($object['start']) ? $object['start']->format('U') : $object['start']); $sql_data['dtstart'] = date('Y-m-d H:i:s', is_object($object['start']) ? $object['start']->format('U') : $object['start']);
$sql_data['dtend'] = date('Y-m-d H:i:s', is_object($object['end']) ? $object['end']->format('U') : $object['end']); $sql_data['dtend'] = date('Y-m-d H:i:s', is_object($object['end']) ? $object['end']->format('U') : $object['end']);
} }

View file

@ -27,23 +27,27 @@ class kolab_storage_folder
/** /**
* The folder name. * The folder name.
*
* @var string * @var string
*/ */
public $name; public $name;
/** /**
* The type of this folder. * The type of this folder.
*
* @var string * @var string
*/ */
public $type; public $type;
/**
* The attached cache object
* @var kolab_storage_cache
*/
public $cache;
private $type_annotation; private $type_annotation;
private $imap; private $imap;
private $info; private $info;
private $owner; private $owner;
private $cache; private $resource_uri;
private $uid2msg = array(); private $uid2msg = array();
@ -72,6 +76,7 @@ class kolab_storage_folder
$metadata = $this->imap->get_metadata($this->name, array(kolab_storage::CTYPE_KEY)); $metadata = $this->imap->get_metadata($this->name, array(kolab_storage::CTYPE_KEY));
$this->type_annotation = $metadata[$this->name][kolab_storage::CTYPE_KEY]; $this->type_annotation = $metadata[$this->name][kolab_storage::CTYPE_KEY];
$this->type = reset(explode('.', $this->type_annotation)); $this->type = reset(explode('.', $this->type_annotation));
$this->resource_uri = null;
$this->cache->set_folder($this); $this->cache->set_folder($this);
} }
@ -180,6 +185,34 @@ class kolab_storage_folder
} }
/**
* Compose a unique resource URI for this IMAP folder
*/
public function get_resource_uri()
{
if (!empty($this->resource_uri))
return $this->resource_uri;
// strip namespace prefix from folder name
$ns = $this->get_namespace();
$nsdata = $this->imap->get_namespace($ns);
if (is_array($nsdata[0]) && strpos($this->name, $nsdata[0][0]) === 0) {
$subpath = substr($this->name, strlen($nsdata[0][0]));
if ($ns == 'other') {
list($user, $suffix) = explode($nsdata[0][1], $subpath);
$subpath = $suffix;
}
}
else {
$subpath = $this->name;
}
// compose fully qualified ressource uri for this instance
$this->resource_uri = 'imap://' . urlencode($this->get_owner()) . '@' . $this->imap->options['host'] . '/' . $subpath;
return $this->resource_uri;
}
/** /**
* Check subscription status of this folder * Check subscription status of this folder
* *
@ -532,7 +565,7 @@ class kolab_storage_folder
{ {
if ($msguid = $this->cache->uid2msguid($uid)) { if ($msguid = $this->cache->uid2msguid($uid)) {
if ($success = $this->imap->move_message($msguid, $target_folder, $this->name)) { if ($success = $this->imap->move_message($msguid, $target_folder, $this->name)) {
// TODO: update cache $this->cache->move($msguid, $uid, $target_folder);
return true; return true;
} }
else { else {