Branch 'dev/kolab3' - 3 commits - plugins/kolab_folders plugins/libkolab
Aleksander Machniak
machniak at kolabsys.com
Mon May 14 13:42:43 CEST 2012
plugins/kolab_folders/kolab_folders.php | 227 ++++----------------------
plugins/kolab_folders/package.xml | 6
plugins/libkolab/lib/kolab_storage.php | 91 +++++++++-
plugins/libkolab/lib/kolab_storage_folder.php | 26 +-
4 files changed, 141 insertions(+), 209 deletions(-)
New commits:
commit a2e191d631a7d018db6e5d9cea777e8eb18afc69
Author: Aleksander Machniak <alec at alec.pl>
Date: Mon May 14 13:41:33 2012 +0200
Improve performance of kolab_storage_folder object creation when
folder type is already known (e.g. in kolab_storage::get_folders())
diff --git a/plugins/libkolab/lib/kolab_storage.php b/plugins/libkolab/lib/kolab_storage.php
index 43f9c72..62b7796 100644
--- a/plugins/libkolab/lib/kolab_storage.php
+++ b/plugins/libkolab/lib/kolab_storage.php
@@ -72,11 +72,11 @@ class kolab_storage
*/
public static function get_folders($type)
{
- $folders = array();
+ $folders = $folderdata = array();
if (self::setup()) {
- foreach ((array)self::list_folders('', '*', $type) as $foldername) {
- $folders[$foldername] = new kolab_storage_folder($foldername, self::$imap);
+ foreach ((array)self::list_folders('', '*', $type, false, $folderdata) as $foldername) {
+ $folders[$foldername] = new kolab_storage_folder($foldername, $folderdata[$foldername]);
}
}
@@ -92,7 +92,7 @@ class kolab_storage
*/
public static function get_folder($folder)
{
- return self::setup() ? new kolab_storage_folder($folder, self::$imap) : null;
+ return self::setup() ? new kolab_storage_folder($folder) : null;
}
@@ -110,7 +110,7 @@ class kolab_storage
$folder = null;
foreach ((array)self::list_folders('', '*', $type) as $foldername) {
if (!$folder)
- $folder = new kolab_storage_folder($foldername, self::$imap);
+ $folder = new kolab_storage_folder($foldername);
else
$folder->set_folder($foldername);
@@ -384,10 +384,11 @@ class kolab_storage
* @param string Optional name pattern
* @param string Data type to list folders for (contact,distribution-list,event,task,note,mail)
* @param string Enable to return subscribed folders only
+ * @param array Will be filled with folder-types data
*
* @return array List of folders
*/
- public static function list_folders($root = '', $mbox = '*', $filter = null, $subscribed = false)
+ public static function list_folders($root = '', $mbox = '*', $filter = null, $subscribed = false, &$folderdata = array())
{
if (!self::setup()) {
return null;
@@ -412,14 +413,14 @@ class kolab_storage
return array();
}
- $regexp = '/^' . preg_quote($filter, '/') . '(\..+)?$/';
+ $folderdata = array_map('implode', $folderdata);
+ $regexp = '/^' . preg_quote($filter, '/') . '(\..+)?$/';
// In some conditions we can skip LIST command (?)
if ($subscribed == false && $filter != 'mail' && $prefix == '*') {
- foreach ($folderdata as $idx => $folder) {
- $type = $folder[self::CTYPE_KEY];
+ foreach ($folderdata as $folder => $type) {
if (!preg_match($regexp, $type)) {
- unset($folderdata[$idx]);
+ unset($folderdata[$folder]);
}
}
return array_keys($folderdata);
@@ -440,7 +441,7 @@ class kolab_storage
// Filter folders list
foreach ($folders as $idx => $folder) {
- $type = !empty($folderdata[$folder]) ? $folderdata[$folder][self::CTYPE_KEY] : null;
+ $type = $folderdata[$folder];
if ($filter == 'mail' && empty($type)) {
continue;
diff --git a/plugins/libkolab/lib/kolab_storage_folder.php b/plugins/libkolab/lib/kolab_storage_folder.php
index d691906..ffbbb5d 100644
--- a/plugins/libkolab/lib/kolab_storage_folder.php
+++ b/plugins/libkolab/lib/kolab_storage_folder.php
@@ -54,30 +54,34 @@ class kolab_storage_folder
/**
* Default constructor
*/
- function __construct($name, $imap = null)
+ function __construct($name, $type = null)
{
- $this->imap = is_object($imap) ? $imap : rcube::get_instance()->get_storage();
+ $this->imap = rcube::get_instance()->get_storage();
$this->imap->set_options(array('skip_deleted' => true));
$this->cache = new kolab_storage_cache($this);
- $this->set_folder($name);
+ $this->set_folder($name, $type);
}
/**
- * Set the IMAP folder name this instance connects to
+ * Set the IMAP folder this instance connects to
*
* @param string The folder name/path
+ * @param string Optional folder type if known
*/
- public function set_folder($name)
+ public function set_folder($name, $type = null)
{
- $this->name = $name;
- $this->imap->set_folder($this->name);
+ if (!$type) {
+ $metadata = $this->imap->get_metadata($name, array(kolab_storage::CTYPE_KEY));
+ $type = $metadata[$this->name][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 = reset(explode('.', $this->type_annotation));
- $this->resource_uri = null;
+ $this->name = $name;
+ $this->type_annotation = $type;
+ $this->type = reset(explode('.', $type));
+ $this->resource_uri = null;
+ $this->imap->set_folder($this->name);
$this->cache->set_folder($this);
}
commit 4ed6758112fdab4a6696b33b25fe87ebb16ce421
Author: Aleksander Machniak <alec at alec.pl>
Date: Mon May 14 13:04:24 2012 +0200
Integrate folders listing functionality from kolab_folders plugin
into kolab_storage class - added public list_folders() method.
Now we can use kolab_storage out of Roundcube application.
diff --git a/plugins/kolab_folders/kolab_folders.php b/plugins/kolab_folders/kolab_folders.php
index 29bcd2f..3e01061 100644
--- a/plugins/kolab_folders/kolab_folders.php
+++ b/plugins/kolab_folders/kolab_folders.php
@@ -30,8 +30,6 @@ class kolab_folders extends rcube_plugin
public $mail_types = array('inbox', 'drafts', 'sentitems', 'outbox', 'wastebasket', 'junkemail');
private $rc;
- const CTYPE_KEY = '/shared/vendor/kolab/folder-type';
-
/**
* Plugin initialization.
@@ -40,6 +38,9 @@ class kolab_folders extends rcube_plugin
{
$this->rc = rcmail::get_instance();
+ // load required plugin
+ $this->require_plugin('libkolab');
+
// Folder listing hooks
$this->add_hook('storage_folders', array($this, 'mailboxes_list'));
@@ -57,68 +58,32 @@ class kolab_folders extends rcube_plugin
*/
function mailboxes_list($args)
{
- if (!$this->metadata_support()) {
+ // infinite loop prevention
+ if ($this->is_processing) {
return $args;
}
- $filter = $args['filter'];
-
- // all-folders request, use core method
- if (!$filter) {
+ if (!$this->metadata_support()) {
return $args;
}
- // get folders types
- $folderdata = $this->get_folder_type_list($args['root'].$args['name'], true);
+ $this->is_processing = true;
- if (!is_array($folderdata)) {
- return $args;
- }
+ // get folders
+ $folders = kolab_storage::list_folders($args['root'], $args['name'], $args['filter'], $args['mode'] == 'LSUB');
- $regexp = '/^' . preg_quote($filter, '/') . '(\..+)?$/';
+ $this->is_processing = false;
- // In some conditions we can skip LIST command (?)
- if ($args['mode'] == 'LIST' && $filter != 'mail'
- && $args['root'] == '' && $args['name'] == '*'
- ) {
- foreach ($folderdata as $folder => $type) {
- if (!preg_match($regexp, $type)) {
- unset($folderdata[$folder]);
- }
- }
- $args['folders'] = array_keys($folderdata);
+ if (!is_array($folders)) {
return $args;
}
- $storage = $this->rc->get_storage();
-
- // Get folders list
- if ($args['mode'] == 'LIST') {
- if (!$storage->check_connection()) {
- return $args;
- }
- $args['folders'] = $storage->conn->listMailboxes($args['root'], $args['name']);
- }
- else {
- $args['folders'] = $this->list_subscribed($args['root'], $args['name']);
+ // Create default folders
+ if ($args['root'] == '' && $args['name'] = '*') {
+ $this->create_default_folders($folders, $args['filter']);
}
- // In case of an error, return empty list
- if (!is_array($args['folders'])) {
- $args['folders'] = array();
- return $args;
- }
-
- // Filter folders list
- foreach ($args['folders'] as $idx => $folder) {
- $type = $folderdata[$folder];
- if ($filter == 'mail' && empty($type)) {
- continue;
- }
- if (empty($type) || !preg_match($regexp, $type)) {
- unset($args['folders'][$idx]);
- }
- }
+ $args['folders'] = $folders;
return $args;
}
@@ -132,10 +97,11 @@ class kolab_folders extends rcube_plugin
return $args;
}
- $table = $args['table'];
+ $table = $args['table'];
+ $storage = $this->rc->get_storage();
// get folders types
- $folderdata = $this->get_folder_type_list('*');
+ $folderdata = $storage->get_metadata('*', kolab_storage::CTYPE_KEY);
if (!is_array($folderdata)) {
return $args;
@@ -146,7 +112,7 @@ class kolab_folders extends rcube_plugin
for ($i=1, $cnt=$table->size(); $i<=$cnt; $i++) {
$attrib = $table->get_row_attribs($i);
$folder = $attrib['foldername']; // UTF7-IMAP
- $type = $folderdata[$folder];
+ $type = !empty($folderdata[$folder]) ? $folderdata[$folder][kolab_storage::CTYPE_KEY] : null;
if (!$type)
$type = 'mail';
@@ -266,8 +232,6 @@ class kolab_folders extends rcube_plugin
{
// Folder actions from folders list
if (empty($args['record'])) {
- // Just clear Horde folders cache and return
- $this->clear_folders_cache();
return $args;
}
@@ -340,11 +304,6 @@ class kolab_folders extends rcube_plugin
}
}
- // Clear Horde folders cache
- if ($result) {
- $this->clear_folders_cache();
- }
-
$args['record']['class'] = self::folder_class_name($ctype);
$args['record']['subscribe'] = $subscribe;
$args['result'] = $result;
@@ -355,7 +314,7 @@ class kolab_folders extends rcube_plugin
/**
* Checks if IMAP server supports any of METADATA, ANNOTATEMORE, ANNOTATEMORE2
*
- * @return boolean
+ * @return boolean
*/
function metadata_support()
{
@@ -376,9 +335,9 @@ class kolab_folders extends rcube_plugin
function get_folder_type($folder)
{
$storage = $this->rc->get_storage();
- $folderdata = $storage->get_metadata($folder, array(kolab_folders::CTYPE_KEY));
+ $folderdata = $storage->get_metadata($folder, kolab_storage::CTYPE_KEY);
- return explode('.', $folderdata[$folder][kolab_folders::CTYPE_KEY]);
+ return explode('.', $folderdata[$folder][kolab_storage::CTYPE_KEY]);
}
/**
@@ -393,112 +352,7 @@ class kolab_folders extends rcube_plugin
{
$storage = $this->rc->get_storage();
- return $storage->set_metadata($folder, array(kolab_folders::CTYPE_KEY => $type));
- }
-
- /**
- * Returns list of subscribed folders (directly from IMAP server)
- *
- * @param string $root Optional root folder
- * @param string $name Optional name pattern
- *
- * @return array List of mailboxes/folders
- */
- private function list_subscribed($root='', $name='*')
- {
- $storage = $this->rc->get_storage();
-
- if (!$storage->check_connection()) {
- return null;
- }
-
- // Code copied from rcube_imap::_list_mailboxes()
- // Server supports LIST-EXTENDED, we can use selection options
- // #1486225: Some dovecot versions returns wrong result using LIST-EXTENDED
- if (!$this->rc->config->get('imap_force_lsub') && $storage->get_capability('LIST-EXTENDED')) {
- // This will also set mailbox options, LSUB doesn't do that
- $a_folders = $storage->conn->listMailboxes($root, $name,
- NULL, array('SUBSCRIBED'));
-
- // remove non-existent folders
- if (is_array($a_folders) && $name = '*' && !empty($storage->conn->data['LIST'])) {
- foreach ($a_folders as $idx => $folder) {
- if (($opts = $storage->conn->data['LIST'][$folder])
- && in_array('\\NonExistent', $opts)
- ) {
- $storage->conn->unsubscribe($folder);
- unset($a_folders[$idx]);
- }
- }
- }
- }
- // retrieve list of folders from IMAP server using LSUB
- else {
- $a_folders = $storage->conn->listSubscribed($root, $name);
-
- // unsubscribe non-existent folders, remove from the list
- if (is_array($a_folders) && $name == '*' && !empty($storage->conn->data['LIST'])) {
- foreach ($a_folders as $idx => $folder) {
- if (!isset($storage->conn->data['LIST'][$folder])
- || in_array('\\Noselect', $storage->conn->data['LIST'][$folder])
- ) {
- // Some servers returns \Noselect for existing folders
- if (!$storage->folder_exists($folder)) {
- $storage->conn->unsubscribe($folder);
- unset($a_folders[$idx]);
- }
- }
- }
- }
- }
-
- return $a_folders;
- }
-
- /**
- * Returns list of folder(s) type(s)
- *
- * @param string $mbox Folder name or pattern
- * @param bool $defaults Enables creation of configured default folders
- *
- * @return array List of folders data, indexed by folder name
- */
- function get_folder_type_list($mbox, $create_defaults = false)
- {
- $storage = $this->rc->get_storage();
-
- // Use mailboxes. prefix so the cache will be cleared by core
- // together with other mailboxes-related cache data
- $cache_key = 'mailboxes.folder-type.'.$mbox;
-
- // get cached metadata
- $metadata = $storage->get_cache($cache_key);
-
- if (!is_array($metadata)) {
- $metadata = $storage->get_metadata($mbox, kolab_folders::CTYPE_KEY);
- $need_update = true;
- }
-
- if (!is_array($metadata)) {
- return false;
- }
-
- // make the result more flat
- if ($need_update) {
- $metadata = array_map('implode', $metadata);
- }
-
- // create default folders if needed
- if ($create_defaults) {
- $this->create_default_folders($metadata, $cache_key);
- }
-
- // write mailboxlist to cache
- if ($need_update) {
- $storage->update_cache($cache_key, $metadata);
- }
-
- return $metadata;
+ return $storage->set_metadata($folder, array(kolab_storage::CTYPE_KEY => $type));
}
/**
@@ -511,7 +365,7 @@ class kolab_folders extends rcube_plugin
function get_default_folder($type)
{
$storage = $this->rc->get_storage();
- $folderdata = $this->get_folder_type_list('*');
+ $folderdata = $storage->get_metadata('*', kolab_storage::CTYPE_KEY);
if (!is_array($folderdata)) {
return null;
@@ -521,7 +375,8 @@ class kolab_folders extends rcube_plugin
$namespace = $storage->get_namespace();
// get all folders of specified type
- $folderdata = array_intersect($folderdata, array($type));
+ $folderdata = array_map('implode', $folderdata);
+ $folderdata = array_intersect($folderdata, array($type));
unset($folders[0]);
foreach ($folderdata as $folder => $data) {
@@ -563,23 +418,23 @@ class kolab_folders extends rcube_plugin
}
/**
- * Clear Horde's folder cache. See Kolab_List::singleton().
- */
- private function clear_folders_cache()
- {
- unset($_SESSION['horde_session_objects']['kolab_folderlist']);
- }
-
- /**
* Creates default folders if they doesn't exist
*/
- private function create_default_folders(&$folderdata, $cache_key = null)
+ private function create_default_folders(&$folders, $filter)
{
$storage = $this->rc->get_storage();
$namespace = $storage->get_namespace();
+ $folderdata = $storage->get_metadata('*', kolab_storage::CTYPE_KEY);
$defaults = array();
$need_update = false;
+ if (!is_array($folderdata)) {
+ return;
+ }
+
+ // "Flattenize" metadata array to become a name->type hash
+ $folderdata = array_map('implode', $folderdata);
+
// Find personal namespace prefix
if (is_array($namespace['personal']) && count($namespace['personal']) == 1) {
$prefix = $namespace['personal'][0][0];
@@ -621,7 +476,7 @@ class kolab_folders extends rcube_plugin
}
// get all folders of specified type
- $folders = array_intersect($folderdata, array($type));
+ $folders = array_intersect($folderdata, array($type));
unset($folders[0]);
// find folders in personal namespace
@@ -653,16 +508,10 @@ class kolab_folders extends rcube_plugin
$result = $this->set_folder_type($foldername, $type);
// add new folder to the result
- if ($result) {
- $folderdata[$foldername] = $type;
- $need_update = true;
+ if ($result && (!$filter || $filter == $type1)) {
+ $folders[] = $foldername;
}
}
-
- // update cache
- if ($need_update && $cache_key) {
- $storage->update_cache($cache_key, $folderdata);
- }
}
}
diff --git a/plugins/kolab_folders/package.xml b/plugins/kolab_folders/package.xml
index 8042ba2..875d614 100644
--- a/plugins/kolab_folders/package.xml
+++ b/plugins/kolab_folders/package.xml
@@ -21,10 +21,10 @@
<email>machniak at kolabsys.com</email>
<active>yes</active>
</lead>
- <date>2011-11-01</date>
+ <date>2012-05-14</date>
<version>
- <release>1.0</release>
- <api>1.0</api>
+ <release>2.0</release>
+ <api>2.0</api>
</version>
<stability>
<release>stable</release>
diff --git a/plugins/libkolab/lib/kolab_storage.php b/plugins/libkolab/lib/kolab_storage.php
index 175bb02..43f9c72 100644
--- a/plugins/libkolab/lib/kolab_storage.php
+++ b/plugins/libkolab/lib/kolab_storage.php
@@ -75,7 +75,7 @@ class kolab_storage
$folders = array();
if (self::setup()) {
- foreach ((array)self::$imap->list_folders('', '*', $type) as $foldername) {
+ foreach ((array)self::list_folders('', '*', $type) as $foldername) {
$folders[$foldername] = new kolab_storage_folder($foldername, self::$imap);
}
}
@@ -108,7 +108,7 @@ class kolab_storage
{
self::setup();
$folder = null;
- foreach ((array)self::$imap->list_folders('', '*', $type) as $foldername) {
+ foreach ((array)self::list_folders('', '*', $type) as $foldername) {
if (!$folder)
$folder = new kolab_storage_folder($foldername, self::$imap);
else
@@ -375,4 +375,82 @@ class kolab_storage
return $select;
}
+
+
+ /**
+ * Returns a list of folder names
+ *
+ * @param string Optional root folder
+ * @param string Optional name pattern
+ * @param string Data type to list folders for (contact,distribution-list,event,task,note,mail)
+ * @param string Enable to return subscribed folders only
+ *
+ * @return array List of folders
+ */
+ public static function list_folders($root = '', $mbox = '*', $filter = null, $subscribed = false)
+ {
+ if (!self::setup()) {
+ return null;
+ }
+
+ if (!$filter) {
+ // Get ALL folders list, standard way
+ if ($subscribed) {
+ return self::$imap->list_folders_subscribed($root, $mbox);
+ }
+ else {
+ return self::$imap->list_folders($root, $mbox);
+ }
+ }
+
+ $prefix = $root . $mbox;
+
+ // get folders types
+ $folderdata = self::$imap->get_metadata($prefix, self::CTYPE_KEY);
+
+ if (!is_array($folderdata)) {
+ return array();
+ }
+
+ $regexp = '/^' . preg_quote($filter, '/') . '(\..+)?$/';
+
+ // In some conditions we can skip LIST command (?)
+ if ($subscribed == false && $filter != 'mail' && $prefix == '*') {
+ foreach ($folderdata as $idx => $folder) {
+ $type = $folder[self::CTYPE_KEY];
+ if (!preg_match($regexp, $type)) {
+ unset($folderdata[$idx]);
+ }
+ }
+ return array_keys($folderdata);
+ }
+
+ // Get folders list
+ if ($subscribed) {
+ $folders = self::$imap->list_folders_subscribed_direct($root, $mbox);
+ }
+ else {
+ $folders = self::$imap->list_folders_direct($root, $mbox);
+ }
+
+ // In case of an error, return empty list (?)
+ if (!is_array($folders)) {
+ return array();
+ }
+
+ // Filter folders list
+ foreach ($folders as $idx => $folder) {
+ $type = !empty($folderdata[$folder]) ? $folderdata[$folder][self::CTYPE_KEY] : null;
+
+ if ($filter == 'mail' && empty($type)) {
+ continue;
+ }
+ if (empty($type) || !preg_match($regexp, $type)) {
+ unset($folders[$idx]);
+ }
+ }
+
+ return $folders;
+ }
+
}
commit dd516006db8b662dac24bded8bd5c129358d6f6c
Author: Aleksander Machniak <machniak at hosted05.klab.cc>
Date: Mon May 14 10:04:59 2012 +0200
Fix argument count for kolab_storage_folder constructor
diff --git a/plugins/libkolab/lib/kolab_storage.php b/plugins/libkolab/lib/kolab_storage.php
index 983a268..175bb02 100644
--- a/plugins/libkolab/lib/kolab_storage.php
+++ b/plugins/libkolab/lib/kolab_storage.php
@@ -92,7 +92,7 @@ class kolab_storage
*/
public static function get_folder($folder)
{
- return self::setup() ? new kolab_storage_folder($folder, null, self::$imap) : null;
+ return self::setup() ? new kolab_storage_folder($folder, self::$imap) : null;
}
More information about the commits
mailing list