Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F256941
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
14 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/plugins/kolab_folders/README b/plugins/kolab_folders/README
index 9edf913b..ac4a56d7 100644
--- a/plugins/kolab_folders/README
+++ b/plugins/kolab_folders/README
@@ -1,23 +1,24 @@
Type-aware folder management/listing for Kolab
Author: Aleksander Machniak <machniak@kolabsys.com>
1. About.
---------
The plugin extends folders handling with features of the Kolab Suite.
With this plugin enabled it is possible to:
- set/get/change folder's type
- filter folders list by folder type.
+ - style folders list rows (in folder manager)
http://www.kolab.org/doc/kolabformat-2.0-html
2. Examples.
------------
To get list of all folders of type 'events' use code:
$RCMAIL->imap->list_mailboxes('', '*', 'events');
Plugin provides also set_folder_type/get_folder_type methods.
diff --git a/plugins/kolab_folders/kolab_folders.php b/plugins/kolab_folders/kolab_folders.php
index c64daf10..7f0a3330 100644
--- a/plugins/kolab_folders/kolab_folders.php
+++ b/plugins/kolab_folders/kolab_folders.php
@@ -1,344 +1,408 @@
<?php
/**
* Type-aware folder management/listing for Kolab
*
- * @version 0.2
+ * @version 0.3
* @author Aleksander Machniak <machniak@kolabsys.com>
*
*
* Copyright (C) 2011, Kolab Systems AG
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
class kolab_folders extends rcube_plugin
{
public $types = array('mail', 'event', 'journal', 'task', 'note', 'contact');
public $mail_types = array('inbox', 'drafts', 'sentitems', 'outbox', 'wastebasket', 'junkemail');
private $rc;
const CTYPE_KEY = '/shared/vendor/kolab/folder-type';
/**
* Plugin initialization.
*/
function init()
{
$this->rc = rcmail::get_instance();
// Folder listing hooks
$this->add_hook('mailboxes_list', array($this, 'mailboxes_list'));
// Folder manager hooks
$this->add_hook('folder_form', array($this, 'folder_form'));
$this->add_hook('folder_update', array($this, 'folder_save'));
$this->add_hook('folder_create', array($this, 'folder_save'));
+ $this->add_hook('folders_list', array($this, 'folders_list'));
}
/**
* Handler for mailboxes_list hook. Enables type-aware lists filtering.
*/
function mailboxes_list($args)
{
if (!$this->metadata_support()) {
return $args;
}
$filter = $args['filter'];
// all-folders request, use core method
if (!$filter) {
return $args;
}
// get folders types
$folderdata = $this->get_folder_type_list($args['root'].$args['name']);
if (!is_array($folderdata)) {
$args['folders'] = false;
return $args;
}
$regexp = '/^' . preg_quote($filter, '/') . '(\..+)?$/';
// In some conditions we can skip LIST command (?)
if ($args['mode'] == 'LIST' && $filter != 'mail'
&& $args['root'] == '' && $args['name'] == '*'
) {
foreach ($folderdata as $folder => $data) {
if (!preg_match($regexp, $data[kolab_folders::CTYPE_KEY])) {
unset ($folderdata[$folder]);
}
}
$args['folders'] = array_keys($folderdata);
return $args;
}
// Get folders list
if ($args['mode'] == 'LIST') {
$args['folders'] = $this->rc->imap->conn->listMailboxes($args['root'], $args['name']);
}
else {
$args['folders'] = $this->list_subscribed($args['root'], $args['name']);
}
// 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) {
$data = $folderdata[$folder];
// Empty data => mail
if ($filter == 'mail' && empty($data)) {
continue;
}
if (empty($data) || !preg_match($regexp, $data[kolab_folders::CTYPE_KEY])) {
unset($args['folders'][$idx]);
}
}
return $args;
}
+ /**
+ * Handler for folders_list hook. Add css classes to folder rows.
+ */
+ function folders_list($args)
+ {
+ if (!$this->metadata_support()) {
+ return $args;
+ }
+
+ $table = $args['table'];
+
+ // get folders types
+ $folderdata = $this->get_folder_type_list('*');
+
+ if (!is_array($folderdata)) {
+ return $args;
+ }
+
+ // Add type-based style for table rows
+ // See kolab_folders::folder_class_name()
+ for ($i=0, $cnt=$table->size(); $i<$cnt; $i++) {
+ $attrib = $table->get_row_attribs($i);
+ $folder = $attrib['foldername']; // UTF7-IMAP
+ $data = $folderdata[$folder];
+
+ if (!empty($data)
+ && ($type = $data[kolab_folders::CTYPE_KEY])
+ && ($class_name = self::folder_class_name($type))
+ ) {
+ $attrib['class'] = trim($attrib['class'] . ' ' . $class_name);
+ $table->set_row_attribs($attrib, $i);
+ }
+ }
+
+ return $args;
+ }
+
/**
* Handler for folder info/edit form (folder_form hook).
* Adds folder type selector.
*/
function folder_form($args)
{
if (!$this->metadata_support()) {
return $args;
}
$mbox = strlen($args['name']) ? $args['name'] : $args['parent_name'];
if (isset($_POST['_ctype'])) {
$new_ctype = trim(get_input_value('_ctype', RCUBE_INPUT_POST));
$new_subtype = trim(get_input_value('_subtype', RCUBE_INPUT_POST));
}
// Get type of the folder or the parent
if (strlen($mbox)) {
list($ctype, $subtype) = $this->get_folder_type($mbox);
}
if (!$ctype) {
$ctype = 'mail';
}
// load translations
$this->add_texts('localization/', false);
$this->include_script('kolab_folders.js');
// build type SELECT fields
$type_select = new html_select(array('name' => '_ctype', 'id' => '_ctype'));
$sub_select = new html_select(array('name' => '_subtype', 'id' => '_subtype'));
foreach ($this->types as $type) {
$type_select->add($this->gettext('foldertype'.$type), $type);
}
// add non-supported type
if (!in_array($ctype, $this->types)) {
$type_select->add($ctype, $ctype);
}
$sub_select->add('', '');
$sub_select->add($this->gettext('default'), 'default');
foreach ($this->mail_types as $type) {
$sub_select->add($this->gettext($type), $type);
}
$args['form']['props']['fieldsets']['settings']['content']['foldertype'] = array(
'label' => $this->gettext('folderctype'),
'value' => $type_select->show(isset($new_ctype) ? $new_ctype : $ctype)
. $sub_select->show(isset($new_subtype) ? $new_subtype : $subtype),
);
return $args;
}
/**
* Handler for folder update/create action (folder_update/folder_create hook).
*/
function folder_save($args)
{
- $ctype = trim(get_input_value('_ctype', RCUBE_INPUT_POST));
- $subtype = trim(get_input_value('_subtype', RCUBE_INPUT_POST));
- $mbox = $args['record']['name'];
- $old_mbox = $args['record']['oldname'];
+ $ctype = trim(get_input_value('_ctype', RCUBE_INPUT_POST));
+ $subtype = trim(get_input_value('_subtype', RCUBE_INPUT_POST));
+ $mbox = $args['record']['name'];
+ $old_mbox = $args['record']['oldname'];
+ $subscribe = $args['record']['subscribe'];
if (empty($ctype)) {
return $args;
}
// @TODO: There can be only one default folder of specified type. Add check for this.
if ($subtype == 'default') {
}
// Subtype sanity-checks
- else if ($subtype && $ctype != 'mail' || !in_array($subtype, $this->mail_types)) {
+ else if ($subtype && ($ctype != 'mail' || !in_array($subtype, $this->mail_types))) {
$subtype = '';
}
$ctype .= $subtype ? '.'.$subtype : '';
// Create folder
if (!strlen($old_mbox)) {
- $result = $this->rc->imap->create_mailbox($mbox, true);
+ // By default don't subscribe to non-mail folders
+ if ($subscribe)
+ $subscribe = preg_match('/^mail/', $ctype);
+
+ $result = $this->rc->imap->create_mailbox($mbox, $subscribe);
// Set folder type
if ($result) {
$this->set_folder_type($mbox, $ctype);
}
}
// Rename folder
else {
if ($old_mbox != $mbox) {
$result = $this->rc->imap->rename_mailbox($old_mbox, $mbox);
}
else {
$result = true;
}
if ($result) {
list($oldtype, $oldsubtype) = $this->get_folder_type($mbox);
$oldtype .= $oldsubtype ? '.'.$oldsubtype : '';
if ($ctype != $oldtype) {
$this->set_folder_type($mbox, $ctype);
}
}
}
+ $args['record']['class'] = self::folder_class_name($ctype);
+ $args['record']['subscribe'] = $subscribe;
+
// Skip folder creation/rename in core
// @TODO: Maybe we should provide folder_create_after and folder_update_after hooks?
// Using create_mailbox/rename_mailbox here looks bad
$args['abort'] = true;
$args['result'] = $result;
return $args;
}
/**
* Checks if IMAP server supports any of METADATA, ANNOTATEMORE, ANNOTATEMORE2
*
* @return boolean
*/
function metadata_support()
{
return $this->rc->imap->get_capability('METADATA') ||
$this->rc->imap->get_capability('ANNOTATEMORE') ||
$this->rc->imap->get_capability('ANNOTATEMORE2');
}
/**
* Checks if IMAP server supports any of METADATA, ANNOTATEMORE, ANNOTATEMORE2
*
* @param string $folder Folder name
*
* @return array Folder content-type
*/
function get_folder_type($folder)
{
$folderdata = $this->rc->imap->get_metadata($folder, array(kolab_folders::CTYPE_KEY));
return explode('.', $folderdata[$folder][kolab_folders::CTYPE_KEY]);
}
/**
* Sets folder content-type.
*
* @param string $folder Folder name
* @param string $type Content type
*
* @return boolean True on success
*/
function set_folder_type($folder, $type='mail')
{
return $this->rc->imap->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='*')
{
$imap = $this->rc->imap;
// 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') && $imap->get_capability('LIST-EXTENDED')) {
// This will also set mailbox options, LSUB doesn't do that
$a_folders = $imap->conn->listMailboxes($root, $name,
NULL, array('SUBSCRIBED'));
// remove non-existent folders
if (is_array($a_folders)) {
foreach ($a_folders as $idx => $folder) {
if ($imap->conn->data['LIST'] && ($opts = $imap->conn->data['LIST'][$folder])
&& in_array('\\NonExistent', $opts)
) {
unset($a_folders[$idx]);
}
}
}
}
// retrieve list of folders from IMAP server using LSUB
else {
$a_folders = $imap->conn->listSubscribed($root, $name);
}
return $a_folders;
}
/**
* Returns list of folder(s) type(s)
*
* @param string $mbox Folder name or pattern
*
* @return array List of folders data, indexed by folder name
*/
function get_folder_type_list($mbox)
{
// Use mailboxes. prefix so the cache will be cleared by core
// together with other mailboxes-related cache data
$cache_key = 'mailboxes.types.'.$mbox;
// get cached metadata
$metadata = $this->rc->imap->get_cache($cache_key);
if (is_array($metadata)) {
return $metadata;
}
$metadata = $this->rc->imap->get_metadata($mbox, kolab_folders::CTYPE_KEY);
if (!is_array($metadata)) {
return false;
}
// write mailboxlist to cache
$this->rc->imap->update_cache($cache_key, $metadata);
return $metadata;
}
-}
+ /**
+ * Returns CSS class name for specified folder type
+ *
+ * @param string $type Folder type
+ *
+ * @return string Class name
+ */
+ static function folder_class_name($type)
+ {
+ list($ctype, $subtype) = explode('.', $type);
+
+ $class[] = 'type-' . ($ctype ? $ctype : 'mail');
+
+ if ($subtype == 'default')
+ $class[] = 'type-default';
+
+ return implode(' ', $class);
+ }
+}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jun 10, 7:37 AM (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
196994
Default Alt Text
(14 KB)
Attached To
Mode
R14 roundcubemail-plugins-kolab
Attached
Detach File
Event Timeline
Log In to Comment