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;
protected /*abstract*/ $objclass;
protected /*abstract*/ $read_func;
protected /*abstract*/ $write_func;
protected $obj;
protected $data;
protected $xmldata;
protected $xmlobject;
protected $loaded = false;
protected $version = 3.0;
const VERSION = '3.0';
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 Cached xml data to initialize with
* @param float Format version
* @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))
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);
$suffix = preg_replace('/[^a-z]+/', '', $type);
$classname = 'kolab_format_' . $suffix;
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);
}
/**
* 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
*
@ -184,6 +205,23 @@ abstract class kolab_format
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*()
*
@ -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
*/
@ -257,22 +328,29 @@ abstract class kolab_format
* Load Kolab object data from the given XML block
*
* @param string XML data
* @return boolean True on success, False on failure
*/
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();
}
/**
* Write object data to XML format
*
* @param float Format version to write
* @return string XML data
*/
public function write()
public function write($version = null)
{
$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())
$this->update_uid();

View file

@ -26,6 +26,7 @@ class kolab_format_configuration extends kolab_format
{
public $CTYPE = 'application/x-vnd.kolab.configuration';
protected $objclass = 'Configuration';
protected $read_func = 'kolabformat::readConfiguration';
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
*

View file

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

View file

@ -26,16 +26,11 @@ class kolab_format_distributionlist extends kolab_format
{
public $CTYPE = 'application/vcard+xml';
protected $read_func = 'kolabformat::readDistlist';
protected $write_func = 'kolabformat::writeDistlist';
protected $objclass = 'DistList';
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
*

View file

@ -24,8 +24,9 @@
class kolab_format_event extends kolab_format_xcal
{
protected $read_func = 'kolabformat::readEvent';
protected $write_func = 'kolabformat::writeEvent';
protected $objclass = 'Event';
protected $read_func = 'readEvent';
protected $write_func = 'writeEvent';
private $kolab2_rolemap = array(
'required' => 'REQ-PARTICIPANT',
@ -43,24 +44,15 @@ class kolab_format_event extends kolab_format_xcal
/**
* Default constructor
* Clones into an instance of libcalendaring's extended EventCal class
*
* @return mixed EventCal object or false on failure
*/
function __construct($xmldata = null)
public function to_libcal()
{
$this->obj = new Event;
$this->xmldata = $xmldata;
return class_exists('kolabcalendaring') ? new EventCal($this->obj) : false;
}
/**
* Clones into an instance of libcalendaring's extended EventCal class
*
* @return mixed EventCal object or false on failure
*/
public function to_libcal()
{
return class_exists('kolabcalendaring') ? new EventCal($this->obj) : false;
}
/**
* Set event properties to the kolabformat object
*

View file

@ -26,16 +26,11 @@ class kolab_format_journal extends kolab_format
{
public $CTYPE = 'application/calendar+xml';
protected $read_func = 'kolabformat::readJournal';
protected $write_func = 'kolabformat::writeJournal';
protected $objclass = 'Journal';
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
*

View file

@ -26,16 +26,11 @@ class kolab_format_note extends kolab_format
{
public $CTYPE = 'application/x-vnd.kolab.note';
protected $read_func = 'kolabformat::readNote';
protected $write_func = 'kolabformat::writeNote';
protected $objclass = 'Note';
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
*

View file

@ -24,16 +24,11 @@
class kolab_format_task extends kolab_format_xcal
{
protected $read_func = 'kolabformat::readTodo';
protected $write_func = 'kolabformat::writeTodo';
protected $objclass = 'Todo';
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
*

View file

@ -31,6 +31,7 @@ class kolab_storage
const SERVERSIDE_SUBSCRIPTION = 0;
const CLIENTSIDE_SUBSCRIPTION = 1;
public static $version = 3.0;
public static $last_error;
private static $ready = false;
@ -49,6 +50,7 @@ class kolab_storage
$rcmail = rcube::get_instance();
self::$config = $rcmail->config;
self::$version = $rcmail->config->get('kolab_format_version', self::$version);
self::$imap = $rcmail->get_storage();
self::$ready = class_exists('kolabformat') &&
(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;
}
$format = kolab_format::factory($object_type);
if (is_a($format, 'PEAR_Error'))
return false;
// check kolab format version
$mime_version = $headers->others['x-kolab-mime-version'];
if (empty($mime_version)) {
$format_version = $headers->others['x-kolab-mime-version'];
if (empty($format_version)) {
list($xmltype, $subtype) = explode('.', $object_type);
$xmlhead = substr($xml, 0, 512);
// detect old Kolab 2.0 format
if (strpos($xmlhead, '<' . $xmltype) !== false && strpos($xmlhead, 'xmlns=') === false)
$mime_version = 2.0;
$format_version = 2.0;
else
$mime_version = 3.0; // assume 3.0
$format_version = 3.0; // assume 3.0
}
if ($mime_version <= 2.0) {
// read Kolab 2.0 format
$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')) {
return false;
}
// get Kolab format handler for the given type
$format = kolab_format::factory($object_type, $format_version);
// XML-to-array
$object = $handler->load($xml);
$format->fromkolab2($object);
}
else {
// load Kolab 3 format using libkolabxml
$format->load($xml);
}
if (is_a($format, 'PEAR_Error'))
return false;
// load Kolab object from XML part
$format->load($xml);
if ($format->is_valid()) {
$object = $format->to_array();
@ -696,13 +684,13 @@ class kolab_storage_folder
// create new kolab_format instance
if (!$format)
$format = kolab_format::factory($type);
$format = kolab_format::factory($type, kolab_storage::$version);
if (PEAR::isError($format))
return false;
$format->set($object);
$xml = $format->write();
$xml = $format->write(kolab_storage::$version);
$object['uid'] = $format->uid; // read UID from format
$object['_formatobj'] = $format;
@ -721,7 +709,7 @@ class kolab_storage_folder
}
$headers['Date'] = date('r');
$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['Message-ID'] = $rcmail->gen_message_id();
$headers['User-Agent'] = $rcmail->config->get('useragent');