Read (old) configuration.dictionary objects with new kolab_storage layer; writing not implemented yet, until libkolabxml supports it
This commit is contained in:
parent
2cd801f7d0
commit
eca8ebafc3
6 changed files with 192 additions and 338 deletions
|
@ -8,8 +8,9 @@
|
|||
*
|
||||
* @version @package_version@
|
||||
* @author Machniak Aleksander <machniak@kolabsys.com>
|
||||
* @author Thomas Bruederli <bruederli@kolabsys.com>
|
||||
*
|
||||
* Copyright (C) 2011, Kolab Systems AG <contact@kolabsys.com>
|
||||
* Copyright (C) 2011-2012, Kolab Systems AG <contact@kolabsys.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
|
@ -29,8 +30,10 @@ class kolab_config extends rcube_plugin
|
|||
{
|
||||
public $task = 'utils';
|
||||
|
||||
private $config;
|
||||
private $enabled;
|
||||
private $default;
|
||||
private $folders;
|
||||
private $dicts = array();
|
||||
|
||||
/**
|
||||
* Required startup method of a Roundcube plugin
|
||||
|
@ -58,17 +61,26 @@ class kolab_config extends rcube_plugin
|
|||
*/
|
||||
private function load()
|
||||
{
|
||||
if ($this->config)
|
||||
// nothing to be done here
|
||||
if (isset($this->folders))
|
||||
return;
|
||||
|
||||
return; // CURRENTLY DISABLED until libkolabxml has support for config objects
|
||||
|
||||
$this->require_plugin('libkolab');
|
||||
|
||||
$this->config = new kolab_configuration();
|
||||
$this->folders = kolab_storage::get_folders('configuration');
|
||||
foreach ($this->folders as $i => $folder) {
|
||||
if ($folder->default) {
|
||||
$this->default = $folder;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if no folder is set as default, choose the first one
|
||||
if (!$this->default)
|
||||
$this->default = $this->folders[0];
|
||||
|
||||
// check if configuration folder exist
|
||||
if (strlen($this->config->dir)) {
|
||||
if ($this->default && $this->default->name) {
|
||||
$this->enabled = true;
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +101,7 @@ class kolab_config extends rcube_plugin
|
|||
}
|
||||
|
||||
$lang = $args['language'];
|
||||
$dict = $this->dict;
|
||||
$dict = $this->read_dictionary($lang, true);
|
||||
|
||||
$dict['type'] = 'dictionary';
|
||||
$dict['language'] = $args['language'];
|
||||
|
@ -97,16 +109,16 @@ class kolab_config extends rcube_plugin
|
|||
|
||||
if (empty($dict['e'])) {
|
||||
// Delete the object
|
||||
$this->config->del($dict);
|
||||
$this->default->delete($dict);
|
||||
}
|
||||
else {
|
||||
// Update the object
|
||||
$this->config->set($dict);
|
||||
// $this->default->save($dict);
|
||||
}
|
||||
|
||||
$args['abort'] = true;
|
||||
|
||||
return $args;
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -125,14 +137,53 @@ class kolab_config extends rcube_plugin
|
|||
}
|
||||
|
||||
$lang = $args['language'];
|
||||
$this->dict = $this->config->get('dictionary.'.$lang);
|
||||
$dict = $this->read_dictionary($lang);
|
||||
|
||||
if (!empty($this->dict)) {
|
||||
$args['dictionary'] = $this->dict['e'];
|
||||
if (!empty($dict)) {
|
||||
$args['dictionary'] = (array)$dict['e'];
|
||||
}
|
||||
|
||||
$args['abort'] = true;
|
||||
|
||||
return $args;
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load dictionary config objects from Kolab storage
|
||||
*
|
||||
* @param string The language (2 chars) to load
|
||||
* @param boolean Only load objects from default folder
|
||||
* @return array Dictionary object as hash array
|
||||
*/
|
||||
private function read_dictionary($lang, $default = false)
|
||||
{
|
||||
if (isset($this->dicts[$lang]))
|
||||
return $this->dicts[$lang];
|
||||
|
||||
$query = array(array('type','=','configuration.dictionary'), array('tags','=',' '.$lang.' '));
|
||||
|
||||
foreach ($this->folders as $folder) {
|
||||
// we only want to read from default folder
|
||||
if ($default && !$folder->default)
|
||||
continue;
|
||||
|
||||
foreach ((array)$folder->select($query) as $object) {
|
||||
if ($object['type'] == 'dictionary' && $object['language'] == $lang) {
|
||||
|
||||
if (is_array($this->dicts[$lang]))
|
||||
$this->dicts[$lang]['e'] = array_merge((array)$this->dicts[$lang]['e'], $object['e']);
|
||||
else
|
||||
$this->dicts[$lang] = $object;
|
||||
|
||||
// make sure the default object is cached
|
||||
if ($folder->default) {
|
||||
$object['e'] = $this->dicts[$lang]['e'];
|
||||
$this->dicts[$lang] = $object;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->dicts[$lang];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Kolab XML handler for configuration (KEP:9).
|
||||
*
|
||||
* @author Aleksander Machniak <machniak@kolabsys.com>
|
||||
*
|
||||
* Copyright (C) 2011, Kolab Systems AG <contact@kolabsys.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
class Horde_Kolab_Format_XML_configuration extends Horde_Kolab_Format_XML {
|
||||
/**
|
||||
* Specific data fields for the configuration object
|
||||
*
|
||||
* @var Kolab
|
||||
*/
|
||||
var $_fields_specific;
|
||||
|
||||
var $_root_version = 2.1;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
function Horde_Kolab_Format_XML_configuration($params = array())
|
||||
{
|
||||
$this->_root_name = 'configuration';
|
||||
|
||||
// Specific configuration fields, in kolab format specification order
|
||||
$this->_fields_specific = array(
|
||||
'application' => array (
|
||||
'type' => HORDE_KOLAB_XML_TYPE_STRING,
|
||||
'value' => HORDE_KOLAB_XML_VALUE_MAYBE_MISSING,
|
||||
),
|
||||
'type' => array(
|
||||
'type' => HORDE_KOLAB_XML_TYPE_STRING,
|
||||
'value' => HORDE_KOLAB_XML_VALUE_NOT_EMPTY,
|
||||
),
|
||||
);
|
||||
|
||||
// Dictionary fields
|
||||
if (!empty($params['subtype']) && preg_match('/^dictionary.*/', $params['subtype'])) {
|
||||
$this->_fields_specific = array_merge($this->_fields_specific, array(
|
||||
'language' => array (
|
||||
'type' => HORDE_KOLAB_XML_TYPE_STRING,
|
||||
'value' => HORDE_KOLAB_XML_VALUE_NOT_EMPTY,
|
||||
),
|
||||
'e' => array(
|
||||
'type' => HORDE_KOLAB_XML_TYPE_MULTIPLE,
|
||||
'value' => HORDE_KOLAB_XML_VALUE_NOT_EMPTY,
|
||||
'array' => array(
|
||||
'type' => HORDE_KOLAB_XML_TYPE_STRING,
|
||||
'value' => HORDE_KOLAB_XML_VALUE_NOT_EMPTY,
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
parent::Horde_Kolab_Format_XML($params);
|
||||
|
||||
unset($this->_fields_basic['body']);
|
||||
unset($this->_fields_basic['categories']);
|
||||
unset($this->_fields_basic['sensitivity']);
|
||||
}
|
||||
}
|
|
@ -1,241 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Kolab configuration storage handler.
|
||||
*
|
||||
* @author Machniak Aleksander <machniak@kolabsys.com>
|
||||
*
|
||||
* Copyright (C) 2011, Kolab Systems AG <contact@kolabsys.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
class kolab_configuration
|
||||
{
|
||||
public $dir;
|
||||
private $rc;
|
||||
private $imap_data = array();
|
||||
|
||||
/**
|
||||
* Class constructor. Establishes IMAP connection.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->rc = rcmail::get_instance();
|
||||
|
||||
// Connect to IMAP
|
||||
$this->rc->imap_connect();
|
||||
|
||||
// Get default configuration directory
|
||||
// @TODO: handle many config directories, according to KEP:9
|
||||
$dirs = $this->rc->imap->list_unsubscribed('', '*', 'configuration');
|
||||
$this->dir = array_shift($dirs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns configuration object
|
||||
*
|
||||
* @param string $type Configuration object type
|
||||
*
|
||||
* @return array Configuration object
|
||||
*/
|
||||
public function get($type)
|
||||
{
|
||||
// If config folder exists
|
||||
if (isset($this->dir[0])) {
|
||||
// search by object type
|
||||
// @TODO: configuration folders shouldn't be big, consider
|
||||
// caching of all objects, then if we extend cache with object type
|
||||
// column we could simply search in cache.
|
||||
// @TODO: handle many config directories, according to KEP:9
|
||||
$ctype = 'application/x-vnd.kolab.configuration' . ($type ? '.'.$type : '');
|
||||
$search = 'HEADER X-Kolab-Type ' . $ctype;
|
||||
|
||||
$this->set_imap_props();
|
||||
$this->rc->imap->search($this->dir, $search, 'US-ASCII', 'date');
|
||||
|
||||
$list = $this->rc->imap->list_headers($this->dir, 1, 'date', 'DESC');
|
||||
$this->reset_imap_props();
|
||||
|
||||
foreach ($list as $idx => $obj) {
|
||||
// @TODO: maybe we could skip parsing the message structure and
|
||||
// get second part's body directly
|
||||
$msg = new rcube_message($obj->uid);
|
||||
$xml = null;
|
||||
|
||||
// get XML part
|
||||
foreach ((array)$msg->attachments as $part) {
|
||||
if ($part->mimetype == 'application/xml') {
|
||||
if (!$part->body)
|
||||
$part->body = $msg->get_part_content($part->mime_id);
|
||||
$xml = $part->body;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// that shouldn't happen
|
||||
if ($xml === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load XML object parser
|
||||
$handler = Horde_Kolab_Format::factory('XML', 'configuration', array('subtype' => $type));
|
||||
if (is_object($handler) && is_a($handler, 'PEAR_Error')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// XML-to-array
|
||||
$object = $handler->load($xml);
|
||||
|
||||
if (is_object($object) && is_a($object, 'PEAR_Error')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$object['mailbox'] = $this->dir;
|
||||
$object['msguid'] = $obj->uid;
|
||||
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves configuration object
|
||||
*
|
||||
* @param array $object Configuration object
|
||||
*
|
||||
* @return bool True on success, False on failre
|
||||
*/
|
||||
public function set($object)
|
||||
{
|
||||
$object['uid'] = md5(uniqid(mt_rand(), true));
|
||||
$raw_msg = $this->build_message($object);
|
||||
|
||||
if ($raw_msg && isset($this->dir[0])) {
|
||||
$result = $this->rc->imap->save_message($this->dir, $raw_msg, '', false);
|
||||
}
|
||||
|
||||
// delete old message
|
||||
if ($result && !empty($object['msguid'])) {
|
||||
$this->rc->imap->delete_message($object['msguid'], $object['mailbox']);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes configuration object
|
||||
*
|
||||
* @param array $object Configuration object
|
||||
*
|
||||
* @return bool True on success, False on failre
|
||||
*/
|
||||
public function del($object)
|
||||
{
|
||||
if (!empty($object['msguid'])) {
|
||||
return $this->rc->imap->delete_message($object['msguid'], $object['mailbox']);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets some rcube_imap settings before searching for config objects
|
||||
*/
|
||||
private function set_imap_props()
|
||||
{
|
||||
// Save old settings
|
||||
$this->imap_data = array(
|
||||
'skip_deleted' => $skip_deleted,
|
||||
'page_size' => $page_size,
|
||||
'list_page' => $list_page,
|
||||
'threading' => $threading,
|
||||
);
|
||||
|
||||
// Configure for configuration folder
|
||||
$this->rc->imap->skip_deleted = true;
|
||||
$this->rc->imap->threading = false;
|
||||
$this->rc->imap->page_size = 100;
|
||||
$this->rc->imap->list_page = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets rcube_imap settings after searching for config objects
|
||||
*/
|
||||
private function reset_imap_props()
|
||||
{
|
||||
// Reset to old settings
|
||||
foreach ($this->imap_data as $key => $val) {
|
||||
$this->rc->imap->$key = $val;
|
||||
}
|
||||
// reset saved search
|
||||
$this->rc->imap->search_set = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates source of the configuration object message
|
||||
*/
|
||||
private function build_message($object)
|
||||
{
|
||||
$MAIL_MIME = new Mail_mime("\r\n");
|
||||
|
||||
$name = 'configuration';
|
||||
|
||||
if (!empty($object['type'])) {
|
||||
$name .= '.' . $object['type'];
|
||||
if ($object['type'] == 'dictionary' && !empty($object['language'])) {
|
||||
$name .= '.' . $object['language'];
|
||||
}
|
||||
}
|
||||
|
||||
$handler = Horde_Kolab_Format::factory('XML', 'configuration',
|
||||
array('subtype' => $object['type']));
|
||||
|
||||
if (is_object($handler) && is_a($handler, 'PEAR_Error')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$xml = $handler->save($object);
|
||||
|
||||
if (is_object($xml) && is_a($xml, 'PEAR_Error')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($ident = $this->rc->user->get_identity()) {
|
||||
$headers['From'] = $ident['email'];
|
||||
$headers['To'] = $ident['email'];
|
||||
}
|
||||
$headers['Date'] = date('r');
|
||||
$headers['X-Kolab-Type'] = 'application/x-vnd.kolab.'.$name;
|
||||
$headers['Subject'] = $object['uid'];
|
||||
$headers['Message-ID'] = rcmail_gen_message_id();
|
||||
$headers['User-Agent'] = $this->rc->config->get('useragent');
|
||||
|
||||
$MAIL_MIME->headers($headers);
|
||||
$MAIL_MIME->setTXTBody('This is a Kolab Groupware object. '
|
||||
.'To view this object you will need an email client that understands the Kolab Groupware format. '
|
||||
.'For a list of such email clients please visit http://www.kolab.org/kolab2-clients.html');
|
||||
|
||||
$MAIL_MIME->addAttachment($xml,
|
||||
'application/xml',
|
||||
$name . '.xml',
|
||||
false, '8bit', 'attachment', RCMAIL_CHARSET, '', '',
|
||||
$this->rc->config->get('mime_param_folding') ? 'quoted-printable' : null,
|
||||
$this->rc->config->get('mime_param_folding') == 2 ? 'quoted-printable' : null,
|
||||
'', RCMAIL_CHARSET
|
||||
);
|
||||
|
||||
return $MAIL_MIME->getMessage();
|
||||
}
|
||||
|
||||
}
|
|
@ -16,10 +16,10 @@
|
|||
<email>machniak@kolabsys.com</email>
|
||||
<active>yes</active>
|
||||
</lead>
|
||||
<date>2011-11-01</date>
|
||||
<date>2012-05-23</date>
|
||||
<version>
|
||||
<release>1.0</release>
|
||||
<api>1.0</api>
|
||||
<release>2.0</release>
|
||||
<api>2.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
|
@ -34,8 +34,6 @@
|
|||
<tasks:replace from="@package_version@" to="version" type="package-info"/>
|
||||
</file>
|
||||
<file name="LICENSE" role="data"></file>
|
||||
<file name="lib/configuration.php" role="php"></file>
|
||||
<file name="lib/kolab_configuration.php" role="php"></file>
|
||||
</dir>
|
||||
<!-- / -->
|
||||
</contents>
|
||||
|
@ -48,7 +46,7 @@
|
|||
<min>1.7.0</min>
|
||||
</pearinstaller>
|
||||
<package>
|
||||
<name>kolab_folders</name>
|
||||
<name>libkolab</name>
|
||||
<uri>http://kolabsys.com</uri>
|
||||
</package>
|
||||
</required>
|
||||
|
|
121
plugins/libkolab/lib/kolab_format_configuration.php
Normal file
121
plugins/libkolab/lib/kolab_format_configuration.php
Normal file
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Kolab Configuration data model class
|
||||
*
|
||||
* @version @package_version@
|
||||
* @author Thomas Bruederli <bruederli@kolabsys.com>
|
||||
*
|
||||
* Copyright (C) 2012, Kolab Systems AG <contact@kolabsys.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
class kolab_format_configuration extends kolab_format
|
||||
{
|
||||
public $CTYPE = 'application/x-vnd.kolab.configuration';
|
||||
|
||||
protected $read_func = 'kolabformat::readConfiguration';
|
||||
protected $write_func = 'kolabformat::writeConfiguration';
|
||||
|
||||
|
||||
function __construct($xmldata = null)
|
||||
{
|
||||
$this->obj = new Configuration;
|
||||
$this->xmldata = $xmldata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set properties to the kolabformat object
|
||||
*
|
||||
* @param array Object data as hash array
|
||||
*/
|
||||
public function set(&$object)
|
||||
{
|
||||
$this->init();
|
||||
|
||||
// set some automatic values if missing
|
||||
# if (!empty($object['uid']))
|
||||
# $this->obj->setUid($object['uid']);
|
||||
|
||||
// TODO: set object propeties
|
||||
|
||||
// cache this data
|
||||
$this->data = $object;
|
||||
unset($this->data['_formatobj']);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function is_valid()
|
||||
{
|
||||
return $this->data || (is_object($this->obj)/* && $this->obj->isValid()*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load data from old Kolab2 format
|
||||
*/
|
||||
public function fromkolab2($record)
|
||||
{
|
||||
$object = array(
|
||||
'uid' => $record['uid'],
|
||||
'changed' => $record['last-modification-date'],
|
||||
);
|
||||
|
||||
$this->data = $object + $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the Configuration object into a hash array data structure
|
||||
*
|
||||
* @return array Config object data as hash array
|
||||
*/
|
||||
public function to_array()
|
||||
{
|
||||
// return cached result
|
||||
if (!empty($this->data))
|
||||
return $this->data;
|
||||
|
||||
$this->init();
|
||||
|
||||
// read object properties
|
||||
$object = array(
|
||||
# 'uid' => $this->obj->uid(),
|
||||
# 'changed' => $this->obj->lastModified(),
|
||||
);
|
||||
|
||||
|
||||
// TODO: read object properties
|
||||
|
||||
$this->data = $object;
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for kolab_storage_cache to get object specific tags to cache
|
||||
*
|
||||
* @return array List of tags to save in cache
|
||||
*/
|
||||
public function get_tags()
|
||||
{
|
||||
$tags = array();
|
||||
|
||||
if ($this->data['type'] == 'dictionary')
|
||||
$tags = array($this->data['language']);
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
}
|
|
@ -56,6 +56,7 @@ class libkolab extends rcube_plugin
|
|||
include_once 'Horde/Kolab/Format/XML.php';
|
||||
include_once 'Horde/Kolab/Format/XML/contact.php';
|
||||
include_once 'Horde/Kolab/Format/XML/event.php';
|
||||
include_once 'Horde_Kolab_Format_XML_configuration.php';
|
||||
|
||||
String::setDefaultCharset('UTF-8');
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue