The "Horde_Kolab_Format" package allows you to easily read and write
the Kolab format within PHP.

Installation of the package
===========================

The package is being distributed as a standard PEAR package by the
Horde project. As long as you have PEAR installed, installation should
be straigt forward.

 pear channel-discover pear.horde.org
 pear install --force channel://pear.horde.org/Horde_Kolab_Format

"pear" will probably complain about the library (and its dependencies)
not being marked stable yet, but the "--force" option allows to ignore
these warnings.

Using the package
=================

This section will present the construction of a short example script
to demonstrate reading/writing an event in the Kolab XML format. The
first required statement is the inclusion of the package:

 require_once 'Horde/Kolab/Format.php';

The API provided by the package is very simple. It only provides a
"load()" and a "save()" function.

In order to have access to these methods it is necessary to create the
"Horde_Kolab_Format" object. The call looks like this:

 $format = Horde_Kolab_Format::factory('Xml', 'Event');

The function takes three arguments:

# "Format type": Currently only "Xml" is supported here.

# "Object type": The type of object you want to read/write. The
  package currently implements "Contact", "Distributionslist",
  "Event", "Note", "Task" and "Hprefs"

The $format variable created above now provides the means to
save and load events in Kolab XML format. In order to save an event we
need to prepare an array with all relevant information about this
event:

 $object = array(
     'uid' => 1,
     'summary' => 'test event',
     'start-date' => time(),
     'end-date' => time() + 24 * 60 * 60,
 );

This is an event that has the "UID" of "1" and carries the title "test
event". It starts right now ("time()") and ends in a day ("time() + 24
* 60 * 60").

This event can now be saved using the "save()" function of the format
handler:

 $xml = $format->save($object);

The function returns the Kolab XML format as a result. This string can
be fed back into the "load()" function:

 $read_object = $format->load($xml);

If we dump the contents of the two variables $xml and
$read_object this will be the result:

 var_dump($xml);
 string(438) "<?xml version="1.0"?>
 <event version="1.0">
   <uid>1</uid>
   
   <categories></categories>
   <creation-date>2008-07-10T12:51:51Z</creation-date>
   <last-modification-date>2008-07-10T12:51:51Z</last-modification-date>
   <sensitivity>public</sensitivity>
   <product-id>Horde::Kolab</product-id>
   
test event
   <start-date>2008-07-10T12:51:51Z</start-date>
   <end-date>2008-07-11T12:51:51Z</end-date>
 </event>
 "

 var_dump($read_object);
 array(11) {
   ["uid"]=>
   string(1) "1"
   ["body"]=>
   string(0) ""
   ["categories"]=>
   array(0) {
   }
   ["creation-date"]=>
   class DateTime#1 (3) {
     public $date =>
     string(19) "2008-07-10 12:51:51"
     public $timezone_type =>
     int(3)
     public $timezone =>
     string(13) "UTC"
   }
   ["last-modification-date"]=>
   class DateTime#1 (3) {
     public $date =>
     string(19) "2008-07-10 12:51:51"
     public $timezone_type =>
     int(3)
     public $timezone =>
     string(13) "UTC"
   }
   ["sensitivity"]=>
   string(6) "public"
   ["product-id"]=>
   string(12) "Horde::Kolab"
   ["summary"]=>
   string(10) "test event"
   ["start-date"]=>
   int(1215694311)
   ["attendee"]=>
   array(0) {
   }
   ["end-date"]=>
   int(1215780711)
 }

We see that the format stores a lot more information than we
originally provided. The resulting XML string does not only contain
the "uid", "summary", "start-date", and "end-date". Several additional
attributes have been added. These were either calculated or set to a
default value.

* "body": holds the event description. We did not specify an event
  description so this value has been set to an empty string.

* "sensitivity": events may be "public" or "private" with "public"
  being the default

* "sensitivity": events may be "public" or "private" with "public"
  being the default

* "categories": Any Kolab object may be member of different
  categories. As we didn't specify a category this value is also
  empty.

* "creation-date": The time stamp of the moment the object was
  created.

* "last-modification-date": The time stamp of the moment the object
  was last modified.

* "product-id": The ID of the product that last touched this
  object. If we use the "Horde_Kolab_Format" package it will always be
  "Horde::Kolab".

If we read the XML data back into an array all these new informations
are available within that array.

Creating your own Kolab XML format
==================================

Currently the "Horde_Kolab_Format" package provides handlers for the
object types "Contact", "Distributionslist", "Event", "Note", and
"Task" as they are defined within the Kolab Format specification. In
addition the Horde specific "Hprefs" type is available. It is used for
storing Horde user preferences in the IMAP store provided by the Kolab
server.

Depending on the web application you might wish to connect with the
Kolab server these object types may not be enough. Do not hesitate to
define your own new type in that case. If you want it to be adopted by
more Kolab clients you should of course discuss it on the Kolab Format
mailing list (http://kolab.org/pipermail/kolab-format/) to get some
feedback on the new type.

The "Horde_Kolab_Format" package makes the definition of a new object
type rather straight forward. The following will explain the creation
of a very simple new object that only saves a single string value.

This time it will be necessary to load the XML format definition,
too. Any new object type will extend this XML definition:

 require_once 'Horde/Kolab/Format.php';
 require_once 'Horde/Kolab/Format/Xml.php';

A new object type is represented by a class that extends
"Horde_Kolab_Format_Xml":

 class Horde_Kolab_Format_Xml_String extends Horde_Kolab_Format_Xml {

     protected $_fields_specific;

     public function __construct()
     {
         $this->_root_name = 'string';

         /** Specific fields of this object type                           
          */
         $this->_fields_specific = array(
             'string' => array(
                 'type' => self::TYPE_STRING,
                 'value' => self::VALUE_MAYBE_MISSING,
             ),
         );

         parent::__construct();
     }
 }

The class needs to end with the name of the object type. Here it is
just "string".

The declaration "var $_fields_specific;" indicates that the new object
type has attributes beyond the basic set required for any Kolab
object. So this part may not be missing for a declaration of a new
type.

The function creating the class ("__construct()") needs to do three
things:

* Declaring the XML root name which will be "string" here. It should
  always match the type name.

* Declaring the specific attributes of the object. This part populates
  the "_fields_specific" variable with an array describing the
  possible object attributes. This will be described in more detail
  further below.

* Calling the parent constructor using
  "parent::__construct()".

The new format can now be used as demonstrated in the initial event
example:

 $format = Horde_Kolab_Format::factory('Xml', 'String');
 $object = array(
     'uid' => 1,
     'string' => 'test string',
 );
 $xml = $format->save($object);
 $read_object = $format->load($xml);
 var_dump($xml);
 var_dump($read_object);

The result looks like this:

 string(347) "<?xml version="1.0"?>
 <string version="1.0">
   <uid>1</uid>
   
   <categories></categories>
   <creation-date>2008-07-10T13:28:36Z</creation-date>
   <last-modification-date>2008-07-10T13:28:36Z</last-modification-date>
   <sensitivity>public</sensitivity>
   <product-id>Horde::Kolab</product-id>
   <string>test string</string>
 </string>
 "

 array(8) {
   ["uid"]=>
   string(1) "1"
   ["body"]=>
   string(0) ""
   ["categories"]=>
   array(0) {
   }
   ["creation-date"]=>
   class DateTime#1 (3) {
     public $date =>
     string(19) "2008-07-10 13:28:36"
     public $timezone_type =>
     int(3)
     public $timezone =>
     string(13) "UTC"
   }
   ["last-modification-date"]=>
   class DateTime#1 (3) {
     public $date =>
     string(19) "2008-07-10 13:28:36"
     public $timezone_type =>
     int(3)
     public $timezone =>
     string(13) "UTC"
   }
   ["sensitivity"]=>
   string(6) "public"
   ["product-id"]=>
   string(12) "Horde::Kolab"
   ["string"]=>
   string(11) "test string"
 }

Allowed fields
==============

There are only a number of valid entries available to specify the
attributes a new object type may contain.

Each entry in the field list will look like this

 'attribute_name' => array(
     'type' => self::TYPE_*,
     'value' => self::VALUE_*,
 ),

"attribute_name" should be a short name describing the value that
should be stored. "type" must be set to one of the following
"self::TYPE_*" type values:

* "self::TYPE_STRING": A string.

* "self::TYPE_INTEGER": A number

* "self::TYPE_BOOLEAN": True or false.

* "self::TYPE_DATE": A date (e.g. 2008/08/08)

* "self::TYPE_DATETIME": A time and a date.

* "self::TYPE_DATE_OR_DATETIME": A date or a time and a
  date.

* "self::TYPE_COLOR": A color (#00BBFF).

* "self::TYPE_COMPOSITE": A composite element that combines
  several attributes.

* "self::TYPE_MULTIPLE": Wrapper for an element that may
  occur several times.

Examples for "self::TYPE_COMPOSITE" and
"self::TYPE_MULTIPLE" can be found in the definitions
currently provided by the "Horde_Kolab_Format" package.

The following "value" settings are allowed:

* "self::VALUE_DEFAULT": An attribute with a default value.

* "self::VALUE_MAYBE_MISSING": An attribute that may be left
  undefined.

* "self::VALUE_NOT_EMPTY": An attribute that will cause an
  error if it is left undefined.

* "self::VALUE_CALCULATE": A complex attribute that gets its
  own function for calculating the correct value.

Examples for "self::VALUE_CALCULATE" can again be found in
the current object types implemented in "Horde_Kolab_Format".

Detailed package documentation
==============================

A detailed documentation based on the code comments and extracted via
phpDocumentor can be found at
http://dev.horde.org/api/framework/. Simply select the package
"Horde_Kolab_Format" in the package selection box in the upper right
corner.
