Page MenuHomePhorge

No OneTemporary

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

Mime Type
text/x-diff
Expires
Tue, Jun 10, 7:37 AM (1 d, 16 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
196994
Default Alt Text
(14 KB)

Event Timeline