Use new libkolab XML object reading/writing functions in preparation of adding Kolab format v2 capabilities

This commit is contained in:
Thomas Bruederli 2012-11-01 20:06:09 +01:00
parent 06e6c43db0
commit d55e56c07c
10 changed files with 127 additions and 92 deletions

View file

@ -31,38 +31,59 @@ abstract class kolab_format
public /*abstract*/ $CTYPE; public /*abstract*/ $CTYPE;
protected /*abstract*/ $objclass;
protected /*abstract*/ $read_func; protected /*abstract*/ $read_func;
protected /*abstract*/ $write_func; protected /*abstract*/ $write_func;
protected $obj; protected $obj;
protected $data; protected $data;
protected $xmldata; protected $xmldata;
protected $xmlobject;
protected $loaded = false; protected $loaded = false;
protected $version = 3.0;
const VERSION = '3.0';
const KTYPE_PREFIX = 'application/x-vnd.kolab.'; const KTYPE_PREFIX = 'application/x-vnd.kolab.';
const PRODUCT_ID = 'Roundcube-libkolab-0.9';
/** /**
* Factory method to instantiate a kolab_format object of the given type * Factory method to instantiate a kolab_format object of the given type and version
* *
* @param string Object type to instantiate * @param string Object type to instantiate
* @param string Cached xml data to initialize with * @param string Cached xml data to initialize with
* @param float Format version
* @return object kolab_format * @return object kolab_format
*/ */
public static function factory($type, $xmldata = null) public static function factory($type, $xmldata = null, $version = 3.0)
{ {
if (!isset(self::$timezone)) if (!isset(self::$timezone))
self::$timezone = new DateTimeZone('UTC'); self::$timezone = new DateTimeZone('UTC');
if (!self::supports($version))
return PEAR::raiseError("No support for Kolab format version " . $version);
$type = preg_replace('/configuration\.[a-z.]+$/', 'configuration', $type); $type = preg_replace('/configuration\.[a-z.]+$/', 'configuration', $type);
$suffix = preg_replace('/[^a-z]+/', '', $type); $suffix = preg_replace('/[^a-z]+/', '', $type);
$classname = 'kolab_format_' . $suffix; $classname = 'kolab_format_' . $suffix;
if (class_exists($classname)) if (class_exists($classname))
return new $classname($xmldata); return new $classname($xmldata, $version);
return PEAR::raiseError("Failed to load Kolab Format wrapper for type " . $type); return PEAR::raiseError("Failed to load Kolab Format wrapper for type " . $type);
} }
/**
* Determine support for the given format version
*
* @param float Format version to check
* @return boolean True if supported, False otherwise
*/
public static function supports($version)
{
if ($version == 2.0)
return class_exists('kolabobject');
// default is version 3
return class_exists('kolabformat');
}
/** /**
* Convert the given date/time value into a cDateTime object * Convert the given date/time value into a cDateTime object
* *
@ -184,6 +205,23 @@ abstract class kolab_format
return preg_replace('/dictionary.[a-z.]+$/', 'dictionary', substr($x_kolab_type, strlen(self::KTYPE_PREFIX))); return preg_replace('/dictionary.[a-z.]+$/', 'dictionary', substr($x_kolab_type, strlen(self::KTYPE_PREFIX)));
} }
/**
* Default constructor of all kolab_format_* objects
*/
public function __construct($xmldata = null, $version = null)
{
$this->obj = new $this->objclass;
$this->xmldata = $xmldata;
if ($version)
$this->version = $version;
// use libkolab module if available
if (class_exists('kolabobject'))
$this->xmlobject = new XMLObject();
}
/** /**
* Check for format errors after calling kolabformat::write*() * Check for format errors after calling kolabformat::write*()
* *
@ -245,6 +283,39 @@ abstract class kolab_format
} }
} }
/**
* Get constant value for libkolab's version parameter
*
* @param float Version value to convert
* @return int Constant value of either kolabobject::KolabV2 or kolabobject::KolabV3 or false if kolabobject module isn't available
*/
protected function libversion($v = null)
{
if (class_exists('kolabobject')) {
$version = $v ?: $this->version;
if ($version <= 2.0)
return kolabobject::KolabV2;
else
return kolabobject::KolabV3;
}
return false;
}
/**
* Determine the correct libkolab(xml) wrapper function for the given call
* depending on the available PHP modules
*/
protected function libfunc($func)
{
if (is_array($func) || strpos($func, '::'))
return $func;
else if (class_exists('kolabobject'))
return array($this->xmlobject, $func);
else
return 'kolabformat::' . $func;
}
/** /**
* Direct getter for object properties * Direct getter for object properties
*/ */
@ -257,22 +328,29 @@ abstract class kolab_format
* Load Kolab object data from the given XML block * Load Kolab object data from the given XML block
* *
* @param string XML data * @param string XML data
* @return boolean True on success, False on failure
*/ */
public function load($xml) public function load($xml)
{ {
$this->obj = call_user_func($this->read_func, $xml, false); $r = call_user_func($this->libfunc($this->read_func), $xml, $this->libversion());
if (is_resource($r))
$this->obj = new $this->objclass($r);
else if (is_a($r, $this->objclass))
$this->obj = $r;
$this->loaded = !$this->format_errors(); $this->loaded = !$this->format_errors();
} }
/** /**
* Write object data to XML format * Write object data to XML format
* *
* @param float Format version to write
* @return string XML data * @return string XML data
*/ */
public function write() public function write($version = null)
{ {
$this->init(); $this->init();
$this->xmldata = call_user_func($this->write_func, $this->obj); $this->xmldata = call_user_func($this->libfunc($this->write_func), $this->obj, $this->libversion($version), self::PRODUCT_ID);
if (!$this->format_errors()) if (!$this->format_errors())
$this->update_uid(); $this->update_uid();

View file

@ -26,6 +26,7 @@ class kolab_format_configuration extends kolab_format
{ {
public $CTYPE = 'application/x-vnd.kolab.configuration'; public $CTYPE = 'application/x-vnd.kolab.configuration';
protected $objclass = 'Configuration';
protected $read_func = 'kolabformat::readConfiguration'; protected $read_func = 'kolabformat::readConfiguration';
protected $write_func = 'kolabformat::writeConfiguration'; protected $write_func = 'kolabformat::writeConfiguration';
@ -35,12 +36,6 @@ class kolab_format_configuration extends kolab_format
); );
function __construct($xmldata = null)
{
$this->obj = new Configuration;
$this->xmldata = $xmldata;
}
/** /**
* Set properties to the kolabformat object * Set properties to the kolabformat object
* *

View file

@ -26,8 +26,9 @@ class kolab_format_contact extends kolab_format
{ {
public $CTYPE = 'application/vcard+xml'; public $CTYPE = 'application/vcard+xml';
protected $read_func = 'kolabformat::readContact'; protected $objclass = 'Contact';
protected $write_func = 'kolabformat::writeContact'; protected $read_func = 'readContact';
protected $write_func = 'writeContact';
public static $fulltext_cols = array('name', 'firstname', 'surname', 'middlename', 'email'); public static $fulltext_cols = array('name', 'firstname', 'surname', 'middlename', 'email');
@ -106,10 +107,9 @@ class kolab_format_contact extends kolab_format
/** /**
* Default constructor * Default constructor
*/ */
function __construct($xmldata = null) function __construct($xmldata = null, $version = 3.0)
{ {
$this->obj = new Contact; parent::__construct($xmldata, $version);
$this->xmldata = $xmldata;
// complete phone types // complete phone types
$this->phonetypes['homefax'] |= Telephone::Home; $this->phonetypes['homefax'] |= Telephone::Home;

View file

@ -26,16 +26,11 @@ class kolab_format_distributionlist extends kolab_format
{ {
public $CTYPE = 'application/vcard+xml'; public $CTYPE = 'application/vcard+xml';
protected $read_func = 'kolabformat::readDistlist'; protected $objclass = 'DistList';
protected $write_func = 'kolabformat::writeDistlist'; protected $read_func = 'readDistlist';
protected $write_func = 'writeDistlist';
function __construct($xmldata = null)
{
$this->obj = new DistList;
$this->xmldata = $xmldata;
}
/** /**
* Set properties to the kolabformat object * Set properties to the kolabformat object
* *

View file

@ -24,8 +24,9 @@
class kolab_format_event extends kolab_format_xcal class kolab_format_event extends kolab_format_xcal
{ {
protected $read_func = 'kolabformat::readEvent'; protected $objclass = 'Event';
protected $write_func = 'kolabformat::writeEvent'; protected $read_func = 'readEvent';
protected $write_func = 'writeEvent';
private $kolab2_rolemap = array( private $kolab2_rolemap = array(
'required' => 'REQ-PARTICIPANT', 'required' => 'REQ-PARTICIPANT',
@ -42,15 +43,6 @@ class kolab_format_event extends kolab_format_xcal
private $kolab2_monthmap = array('', 'january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'); private $kolab2_monthmap = array('', 'january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december');
/**
* Default constructor
*/
function __construct($xmldata = null)
{
$this->obj = new Event;
$this->xmldata = $xmldata;
}
/** /**
* Clones into an instance of libcalendaring's extended EventCal class * Clones into an instance of libcalendaring's extended EventCal class
* *

View file

@ -26,16 +26,11 @@ class kolab_format_journal extends kolab_format
{ {
public $CTYPE = 'application/calendar+xml'; public $CTYPE = 'application/calendar+xml';
protected $read_func = 'kolabformat::readJournal'; protected $objclass = 'Journal';
protected $write_func = 'kolabformat::writeJournal'; protected $read_func = 'readJournal';
protected $write_func = 'writeJournal';
function __construct($xmldata = null)
{
$this->obj = new Journal;
$this->xmldata = $xmldata;
}
/** /**
* Set properties to the kolabformat object * Set properties to the kolabformat object
* *

View file

@ -26,16 +26,11 @@ class kolab_format_note extends kolab_format
{ {
public $CTYPE = 'application/x-vnd.kolab.note'; public $CTYPE = 'application/x-vnd.kolab.note';
protected $read_func = 'kolabformat::readNote'; protected $objclass = 'Note';
protected $write_func = 'kolabformat::writeNote'; protected $read_func = 'readNote';
protected $write_func = 'writeNote';
function __construct($xmldata = null)
{
$this->obj = new Note;
$this->xmldata = $xmldata;
}
/** /**
* Set properties to the kolabformat object * Set properties to the kolabformat object
* *

View file

@ -24,16 +24,11 @@
class kolab_format_task extends kolab_format_xcal class kolab_format_task extends kolab_format_xcal
{ {
protected $read_func = 'kolabformat::readTodo'; protected $objclass = 'Todo';
protected $write_func = 'kolabformat::writeTodo'; protected $read_func = 'readTodo';
protected $write_func = 'writeTodo';
function __construct($xmldata = null)
{
$this->obj = new Todo;
$this->xmldata = $xmldata;
}
/** /**
* Set properties to the kolabformat object * Set properties to the kolabformat object
* *

View file

@ -31,6 +31,7 @@ class kolab_storage
const SERVERSIDE_SUBSCRIPTION = 0; const SERVERSIDE_SUBSCRIPTION = 0;
const CLIENTSIDE_SUBSCRIPTION = 1; const CLIENTSIDE_SUBSCRIPTION = 1;
public static $version = 3.0;
public static $last_error; public static $last_error;
private static $ready = false; private static $ready = false;
@ -49,6 +50,7 @@ class kolab_storage
$rcmail = rcube::get_instance(); $rcmail = rcube::get_instance();
self::$config = $rcmail->config; self::$config = $rcmail->config;
self::$version = $rcmail->config->get('kolab_format_version', self::$version);
self::$imap = $rcmail->get_storage(); self::$imap = $rcmail->get_storage();
self::$ready = class_exists('kolabformat') && self::$ready = class_exists('kolabformat') &&
(self::$imap->get_capability('METADATA') || self::$imap->get_capability('ANNOTATEMORE') || self::$imap->get_capability('ANNOTATEMORE2')); (self::$imap->get_capability('METADATA') || self::$imap->get_capability('ANNOTATEMORE') || self::$imap->get_capability('ANNOTATEMORE2'));

View file

@ -466,39 +466,27 @@ class kolab_storage_folder
return false; return false;
} }
$format = kolab_format::factory($object_type);
if (is_a($format, 'PEAR_Error'))
return false;
// check kolab format version // check kolab format version
$mime_version = $headers->others['x-kolab-mime-version']; $format_version = $headers->others['x-kolab-mime-version'];
if (empty($mime_version)) { if (empty($format_version)) {
list($xmltype, $subtype) = explode('.', $object_type); list($xmltype, $subtype) = explode('.', $object_type);
$xmlhead = substr($xml, 0, 512); $xmlhead = substr($xml, 0, 512);
// detect old Kolab 2.0 format // detect old Kolab 2.0 format
if (strpos($xmlhead, '<' . $xmltype) !== false && strpos($xmlhead, 'xmlns=') === false) if (strpos($xmlhead, '<' . $xmltype) !== false && strpos($xmlhead, 'xmlns=') === false)
$mime_version = 2.0; $format_version = 2.0;
else else
$mime_version = 3.0; // assume 3.0 $format_version = 3.0; // assume 3.0
} }
if ($mime_version <= 2.0) { // get Kolab format handler for the given type
// read Kolab 2.0 format $format = kolab_format::factory($object_type, $format_version);
$handler = class_exists('Horde_Kolab_Format') ? Horde_Kolab_Format::factory('XML', $xmltype, array('subtype' => $subtype)) : null;
if (!is_object($handler) || is_a($handler, 'PEAR_Error')) { if (is_a($format, 'PEAR_Error'))
return false; return false;
}
// XML-to-array // load Kolab object from XML part
$object = $handler->load($xml);
$format->fromkolab2($object);
}
else {
// load Kolab 3 format using libkolabxml
$format->load($xml); $format->load($xml);
}
if ($format->is_valid()) { if ($format->is_valid()) {
$object = $format->to_array(); $object = $format->to_array();
@ -696,13 +684,13 @@ class kolab_storage_folder
// create new kolab_format instance // create new kolab_format instance
if (!$format) if (!$format)
$format = kolab_format::factory($type); $format = kolab_format::factory($type, kolab_storage::$version);
if (PEAR::isError($format)) if (PEAR::isError($format))
return false; return false;
$format->set($object); $format->set($object);
$xml = $format->write(); $xml = $format->write(kolab_storage::$version);
$object['uid'] = $format->uid; // read UID from format $object['uid'] = $format->uid; // read UID from format
$object['_formatobj'] = $format; $object['_formatobj'] = $format;
@ -721,7 +709,7 @@ class kolab_storage_folder
} }
$headers['Date'] = date('r'); $headers['Date'] = date('r');
$headers['X-Kolab-Type'] = kolab_format::KTYPE_PREFIX . $type; $headers['X-Kolab-Type'] = kolab_format::KTYPE_PREFIX . $type;
$headers['X-Kolab-Mime-Version'] = kolab_format::VERSION; $headers['X-Kolab-Mime-Version'] = kolab_storage::$version;
$headers['Subject'] = $object['uid']; $headers['Subject'] = $object['uid'];
// $headers['Message-ID'] = $rcmail->gen_message_id(); // $headers['Message-ID'] = $rcmail->gen_message_id();
$headers['User-Agent'] = $rcmail->config->get('useragent'); $headers['User-Agent'] = $rcmail->config->get('useragent');