plugins/calendar plugins/kolab_delegation
Aleksander Machniak
machniak at kolabsys.com
Thu Dec 13 13:12:17 CET 2012
plugins/calendar/calendar.php | 22 ++-
plugins/calendar/drivers/kolab/kolab_driver.php | 10 +
plugins/calendar/lib/calendar_itip.php | 6
plugins/kolab_delegation/kolab_delegation.js | 21 +++
plugins/kolab_delegation/kolab_delegation.php | 90 ++++++++++++-
plugins/kolab_delegation/kolab_delegation_engine.php | 128 ++++++++++++++++++-
6 files changed, 261 insertions(+), 16 deletions(-)
New commits:
commit 3be3065941f993df74d4112a6c3aeb9f03dbe780
Author: Aleksander Machniak <machniak at kolabsys.com>
Date: Thu Dec 13 13:10:07 2012 +0100
Delegation support in calendar event invitations handling
diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 24d929a..eafb015 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -209,9 +209,13 @@ class calendar extends rcube_plugin
{
if (!$this->itip) {
require_once($this->home . '/lib/calendar_itip.php');
- $this->itip = new calendar_itip($this);
+
+ $plugin = $this->rc->plugins->exec_hook('calendar_load_itip',
+ array('identity' => null));
+
+ $this->itip = new calendar_itip($this, $plugin['identity']);
}
-
+
return $this->itip;
}
@@ -727,7 +731,7 @@ class calendar extends rcube_plugin
if ($numcals <= 1)
$calendar_select = null;
}
-
+
if ($status == 'unknown') {
$html = html::div('rsvp-status', $this->gettext('notanattendee'));
$action = 'import';
@@ -738,7 +742,7 @@ class calendar extends rcube_plugin
$action = ''; // nothing to do here
}
}
-
+
$default_calendar = $calendar_select ? $this->get_default_calendar(true) : null;
$this->rc->output->command('plugin.update_event_rsvp_status', array(
'uid' => $event['uid'],
@@ -1974,7 +1978,15 @@ class calendar extends rcube_plugin
*/
private function get_user_emails()
{
- $emails = array($this->rc->user->get_username());
+ $emails = array();
+ $plugin = $this->rc->plugins->exec_hook('calendar_user_emails', array('emails' => $emails));
+ $emails = $plugin['emails'];
+
+ if ($plugin['abort']) {
+ return $emails;
+ }
+
+ $emails[] = $this->rc->user->get_username();
foreach ($this->rc->user->list_identities() as $identity)
$emails[] = $identity['email'];
diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php
index 4787445..0d913a3 100644
--- a/plugins/calendar/drivers/kolab/kolab_driver.php
+++ b/plugins/calendar/drivers/kolab/kolab_driver.php
@@ -147,6 +147,16 @@ class kolab_driver extends calendar_driver
protected function filter_calendars($writable = false, $active = false, $personal = false)
{
$calendars = array();
+
+ $plugin = $this->rc->plugins->exec_hook('calendar_list_filter', array(
+ 'list' => $this->calendars, 'calendars' => $calendars,
+ 'writable' => $writable, 'active' => $active, 'personal' => $personal,
+ ));
+
+ if ($plugin['abort']) {
+ return $plugin['calendars'];
+ }
+
foreach ($this->calendars as $cal) {
if (!$cal->ready) {
continue;
diff --git a/plugins/calendar/lib/calendar_itip.php b/plugins/calendar/lib/calendar_itip.php
index dc4cfa0..40d9786 100644
--- a/plugins/calendar/lib/calendar_itip.php
+++ b/plugins/calendar/lib/calendar_itip.php
@@ -28,14 +28,14 @@ class calendar_itip
{
private $rc;
private $cal;
- private $event;
+ private $sender;
private $itip_send = false;
- function __construct($cal)
+ function __construct($cal, $identity = null)
{
$this->cal = $cal;
$this->rc = $cal->rc;
- $this->sender = $this->rc->user->get_identity();
+ $this->sender = $identity ? $identity : $this->rc->user->get_identity();
$this->cal->add_hook('smtp_connect', array($this, 'smtp_connect_hook'));
}
diff --git a/plugins/kolab_delegation/kolab_delegation.js b/plugins/kolab_delegation/kolab_delegation.js
index 2462fa3..75e77b8 100644
--- a/plugins/kolab_delegation/kolab_delegation.js
+++ b/plugins/kolab_delegation/kolab_delegation.js
@@ -22,6 +22,14 @@
*/
window.rcmail && rcmail.addEventListener('init', function(evt) {
+ if (rcmail.env.task == 'mail') {
+ // set delegator context for calendar requests on invitation message
+ rcmail.addEventListener('requestcalendar/event', function(o) { rcmail.event_delegator_request(o); });
+ rcmail.addEventListener('requestcalendar/mailimportevent', function(o) { rcmail.event_delegator_request(o); });
+ }
+ else if (rcmail.env.task != 'settings')
+ return;
+
// add Delegation section to the list
var tab = $('<span>').attr('id', 'settingstabplugindelegation').addClass('tablink'),
button = $('<a>').attr('href', rcmail.env.comm_path+'&_action=plugin.delegation')
@@ -218,3 +226,16 @@ rcube_webmail.prototype.delegate_save_complete = function(p)
this.enable_command('delegate-delete', false);
}
};
+
+rcube_webmail.prototype.event_delegator_request = function(data)
+{
+ if (!this.env.delegator_context)
+ return;
+
+ if (typeof data === 'object')
+ data._context = this.env.delegator_context;
+ else
+ data += '&_context=' + this.env.delegator_context;
+
+ return data;
+};
diff --git a/plugins/kolab_delegation/kolab_delegation.php b/plugins/kolab_delegation/kolab_delegation.php
index b7abfd4..6b37e3f 100644
--- a/plugins/kolab_delegation/kolab_delegation.php
+++ b/plugins/kolab_delegation/kolab_delegation.php
@@ -25,7 +25,7 @@
class kolab_delegation extends rcube_plugin
{
- public $task = 'login|mail|settings';
+ public $task = 'login|mail|settings|calendar';
private $rc;
private $engine;
@@ -41,10 +41,19 @@ class kolab_delegation extends rcube_plugin
$this->require_plugin('libkolab');
$this->require_plugin('kolab_auth');
- $this->add_hook('login_after', array($this, 'login_hook'));
+ // on-login delegation initialization
+ $this->add_hook('login_after', array($this, 'login_hook'));
+ // on-check-recent delegation support
$this->add_hook('check_recent', array($this, 'check_recent_hook'));
+ // delegation support in Calendar plugin
+ $this->add_hook('message_load', array($this, 'message_load'));
+ $this->add_hook('calendar_user_emails', array($this, 'calendar_user_emails'));
+ $this->add_hook('calendar_list_filter', array($this, 'calendar_list_filter'));
+ $this->add_hook('calendar_load_itip', array($this, 'calendar_load_itip'));
+
if ($this->rc->task == 'settings') {
+ // delegation management interface
$this->register_action('plugin.delegation', array($this, 'controller_ui'));
$this->register_action('plugin.delegation-delete', array($this, 'controller_action'));
$this->register_action('plugin.delegation-save', array($this, 'controller_action'));
@@ -105,7 +114,7 @@ class kolab_delegation extends rcube_plugin
return $args;
}
- if (empty($_SESSION['delegator_uids'])) {
+ if (empty($_SESSION['delegators'])) {
return $args;
}
@@ -113,7 +122,7 @@ class kolab_delegation extends rcube_plugin
$other_ns = $storage->get_namespace('other');
$folders = $storage->list_folders_subscribed('', '*', 'mail');
- foreach ($_SESSION['delegator_uids'] as $uid) {
+ foreach (array_keys($_SESSION['delegators']) as $uid) {
foreach ($other_ns as $ns) {
$folder = $ns[0] . $uid;
if (in_array($folder, $folders) && !in_array($folder, $args['folders'])) {
@@ -126,6 +135,79 @@ class kolab_delegation extends rcube_plugin
}
/**
+ * E-mail message loading action
+ */
+ public function message_load($args)
+ {
+ // This is a place where we detect delegate context
+ // So we can handle event invitations on behalf of delegator
+ // @TODO: should we do this only in delegators' folders?
+
+ $engine = $this->engine();
+ $context = $engine->delegator_context_from_message($args['object']);
+
+ if ($context) {
+ $this->rc->output->set_env('delegator_context', $context);
+ $this->include_script('kolab_delegation.js');
+ }
+
+ return $args;
+ }
+
+ /**
+ * calendar::get_user_emails() handler
+ */
+ public function calendar_user_emails($args)
+ {
+ // In delegator context we'll use delegator's addresses
+ // instead of current user addresses
+
+ $engine = $this->engine();
+
+ if ($context = $engine->delegator_context()) {
+ $args['emails'] = $_SESSION['delegators'][$context];
+ $args['abort'] = true;
+ }
+
+ return $args;
+ }
+
+ /**
+ * calendar_driver::list_calendars() handler
+ */
+ public function calendar_list_filter($args)
+ {
+ // In delegator context we'll use delegator's folders
+ // instead of current user folders
+
+ $engine = $this->engine();
+
+ if ($engine->delegator_context()) {
+ $args['calendars'] = $engine->delegator_folder_filter($args);
+ $args['abort'] = true;
+ }
+
+ return $args;
+ }
+
+ /**
+ * calendar::load_itip() handler
+ */
+ public function calendar_load_itip($args)
+ {
+ // In delegator context we'll use delegator's address/name
+ // for invitation responses
+
+ $engine = $this->engine();
+
+ if ($engine->delegator_context()) {
+ $args['identity'] = $engine->delegator_identity();
+ }
+
+ return $args;
+ }
+
+ /**
* Delegation UI handler
*/
public function controller_ui()
diff --git a/plugins/kolab_delegation/kolab_delegation_engine.php b/plugins/kolab_delegation/kolab_delegation_engine.php
index 2bb6b70..f2a7125 100644
--- a/plugins/kolab_delegation/kolab_delegation_engine.php
+++ b/plugins/kolab_delegation/kolab_delegation_engine.php
@@ -25,6 +25,8 @@
class kolab_delegation_engine
{
+ public $context;
+
private $rc;
private $ldap_filter;
private $ldap_delegate_field;
@@ -532,9 +534,8 @@ class kolab_delegation_engine
// for every delegator...
foreach ($delegators as $delegator) {
- $uids[] = $delegator['imap_uid'];
- $email_arr = $delegator['email'];
- $diff = array_intersect($emails, $email_arr);
+ $uids[$delegator['imap_uid']] = $email_arr = $delegator['email'];
+ $diff = array_intersect($emails, $email_arr);
// identity with delegator's email already exist, do nothing
if (count($diff)) {
@@ -545,6 +546,8 @@ class kolab_delegation_engine
// create identities for delegator emails
foreach ($email_arr as $email) {
$default['email'] = $email;
+ // @TODO: "Username" or "Delegatorname" or "Username on behalf of Delegatorname"
+ //$default['name'] = $delegator['email'];
$this->rc->user->insert_identity($default);
}
@@ -584,7 +587,124 @@ class kolab_delegation_engine
}
}
- $_SESSION['delegator_uids'] = $uids;
+ $_SESSION['delegators'] = $uids;
+ }
+
+ /**
+ * Sets delegator context according to email message recipient
+ *
+ * @param rcube_message $message Email message object
+ */
+ public function delegator_context_from_message($message)
+ {
+ if (empty($_SESSION['delegators'])) {
+ return;
+ }
+
+ // Match delegators' addresses with message To: address
+ // @TODO: Is this reliable enough?
+ // Roundcube sends invitations to every attendee separately,
+ // but maybe there's a software which sends with CC header or many addresses in To:
+
+ $emails = $message->get_header('to');
+ $emails = rcube_mime::decode_address_list($emails, null, false);
+
+ foreach ($emails as $email) {
+ foreach ($_SESSION['delegators'] as $uid => $addresses) {
+ if (in_array($email['mailto'], $addresses)) {
+ return $this->context = $uid;
+ }
+ }
+ }
+ }
+
+ /**
+ * Return (set) current delegator context
+ *
+ * @return string Delegator UID
+ */
+ public function delegator_context()
+ {
+ if (!$this->context && !empty($_SESSION['delegators'])) {
+ $context = rcube_utils::get_input_value('_context', rcube_utils::INPUT_GPC);
+ if ($context && isset($_SESSION['delegators'][$context])) {
+ $this->context = $context;
+ }
+ }
+
+ return $this->context;
+ }
+
+ /**
+ * Return identity of the current delegator
+ *
+ * @return array Identity data (name and email)
+ */
+ public function delegator_identity()
+ {
+ if (!$this->context) {
+ return;
+ }
+
+ $identities = $this->rc->user->list_identities();
+ $emails = $_SESSION['delegators'][$this->context];
+
+ foreach ($identities as $ident) {
+ if (in_array($ident['email'], $emails)) {
+ return $ident;
+ }
+ }
+ }
+
+ /**
+ * Filters list of calendars according to delegator context
+ *
+ * @param array $args Plugin hook arguments
+ *
+ * @return array List of calendars
+ */
+ public function delegator_folder_filter($args)
+ {
+ if (empty($this->context)) {
+ return;
+ }
+
+ $storage = $this->rc->get_storage();
+ $other_ns = $storage->get_namespace('other');
+ $delim = $storage->get_hierarchy_delimiter();
+ $calendars = array();
+
+ // code parts derived from kolab_driver::filter_calendars()
+ foreach ($args['list'] as $cal) {
+ if (!$cal->ready) {
+ continue;
+ }
+ if ($args['writeable'] && $cal->readonly) {
+ continue;
+ }
+ if ($args['active'] && !$cal->storage->is_active()) {
+ continue;
+ }
+ if ($args['personal']) {
+ $ns = $cal->get_namespace();
+ $name = $cal->get_realname(); // UTF-7 IMAP folder name
+
+ if ($ns != 'other') {
+ continue;
+ }
+
+ foreach ($other_ns as $ns) {
+ $folder = $ns[0] . $this->context . $delim;
+ if (strpos($name, $folder) !== 0) {
+ continue;
+ }
+ }
+ }
+
+ $calendars[$cal->id] = $cal;
+ }
+
+ return $calendars;
}
/**
More information about the commits
mailing list