Replace other user folders uids with display name (Bifrost#T216238)
Extends existing functionality that worked in kolab plugins' UI in a way that: - ldap lookups are optionally cached - replacing is done also in Mail/Settings parts of the UI - object_prettyname() uses the same technique as folders listings
This commit is contained in:
parent
9da21b887c
commit
acd1740a29
4 changed files with 177 additions and 48 deletions
|
@ -72,6 +72,11 @@ class kolab_folders extends rcube_plugin
|
||||||
// ACL plugin hooks
|
// ACL plugin hooks
|
||||||
$this->add_hook('acl_rights_simple', array($this, 'acl_rights_simple'));
|
$this->add_hook('acl_rights_simple', array($this, 'acl_rights_simple'));
|
||||||
$this->add_hook('acl_rights_supported', array($this, 'acl_rights_supported'));
|
$this->add_hook('acl_rights_supported', array($this, 'acl_rights_supported'));
|
||||||
|
|
||||||
|
// Resolving other user folder names
|
||||||
|
$this->add_hook('render_mailboxlist', array($this, 'render_folderlist'));
|
||||||
|
$this->add_hook('render_folder_selector', array($this, 'render_folderlist'));
|
||||||
|
$this->add_hook('folders_list', array($this, 'render_folderlist'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -709,6 +714,7 @@ class kolab_folders extends rcube_plugin
|
||||||
* Static getter for default folder of the given type
|
* Static getter for default folder of the given type
|
||||||
*
|
*
|
||||||
* @param string $type Folder type
|
* @param string $type Folder type
|
||||||
|
*
|
||||||
* @return string Folder name
|
* @return string Folder name
|
||||||
*/
|
*/
|
||||||
public static function default_folder($type)
|
public static function default_folder($type)
|
||||||
|
@ -781,4 +787,74 @@ class kolab_folders extends rcube_plugin
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for various folders list widgets (hooks)
|
||||||
|
*
|
||||||
|
* @param array $args Hash array with hook parameters
|
||||||
|
*
|
||||||
|
* @return array Hash array with modified hook parameters
|
||||||
|
*/
|
||||||
|
public function render_folderlist($args)
|
||||||
|
{
|
||||||
|
$storage = $this->rc->get_storage();
|
||||||
|
$ns_other = $storage->get_namespace('other');
|
||||||
|
$is_fl = $this->rc->plugins->is_processing('folders_list');
|
||||||
|
|
||||||
|
foreach ((array) $ns_other as $root) {
|
||||||
|
$delim = $root[1];
|
||||||
|
$prefix = rtrim($root[0], $delim);
|
||||||
|
$length = strlen($prefix);
|
||||||
|
|
||||||
|
if (!$length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// folders_list hook mode
|
||||||
|
if ($is_fl) {
|
||||||
|
foreach ((array) $args['list'] as $folder_name => $folder) {
|
||||||
|
if (strpos($folder_name, $root[0]) === 0 && !substr_count($folder_name, $root[1], $length+1)) {
|
||||||
|
if ($name = $this->folder_id2username(substr($folder_name, $length+1))) {
|
||||||
|
$old = $args['list'][$folder_name]['display'];
|
||||||
|
$content = $args['list'][$folder_name]['content'];
|
||||||
|
|
||||||
|
$name = rcube::Q($name);
|
||||||
|
$content = str_replace(">$old<", ">$name<", $content);
|
||||||
|
|
||||||
|
$args['list'][$folder_name]['display'] = $name;
|
||||||
|
$args['list'][$folder_name]['content'] = $content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Re-sort the list
|
||||||
|
}
|
||||||
|
// render_* hooks mode
|
||||||
|
else if (!empty($args['list'][$prefix]) && !empty($args['list'][$prefix]['folders'])) {
|
||||||
|
$map = array();
|
||||||
|
foreach ($args['list'][$prefix]['folders'] as $folder_name => $folder) {
|
||||||
|
if ($name = $this->folder_id2username($folder_name)) {
|
||||||
|
$args['list'][$prefix]['folders'][$folder_name]['name'] = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
$map[$folder_name] = $name ?: $args['list'][$prefix]['folders'][$folder_name]['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-sort the list
|
||||||
|
uasort($map, 'strcoll');
|
||||||
|
$args['list'][$prefix]['folders'] = array_replace($map, $args['list'][$prefix]['folders']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map other user (imap) folder identifier to user name
|
||||||
|
* @see kolab_storage::folder_id2user()
|
||||||
|
*/
|
||||||
|
private static function folder_id2username($uid)
|
||||||
|
{
|
||||||
|
return kolab_storage::folder_id2user($uid, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,18 @@ $config['kolab_users_id_attrib'] = null;
|
||||||
// Use these attributes when searching users in LDAP
|
// Use these attributes when searching users in LDAP
|
||||||
$config['kolab_users_search_attrib'] = array('cn','mail','alias');
|
$config['kolab_users_search_attrib'] = array('cn','mail','alias');
|
||||||
|
|
||||||
|
// Which property of the LDAP user record to use as a display name.
|
||||||
|
// Defaults to the 'kolab_auth_name' configuration option.
|
||||||
|
$config['kolab_users_name_field'] = null;
|
||||||
|
|
||||||
|
// Type of cache for uid-to-user map. Supported: 'db', 'apc', 'memcache' and 'memcached'.
|
||||||
|
// Note: This stores only other user folder identifier to user attributes map.
|
||||||
|
$config['kolab_users_cache'] = null;
|
||||||
|
|
||||||
|
// lifetime of shared folder mapping cache
|
||||||
|
// possible units: s, m, h, d, w
|
||||||
|
$config['kolab_users_cache_ttl'] = '10d';
|
||||||
|
|
||||||
// JSON-RPC endpoint configuration of the Bonnie web service providing historic data for groupware objects
|
// JSON-RPC endpoint configuration of the Bonnie web service providing historic data for groupware objects
|
||||||
$config['kolab_bonnie_api'] = array(
|
$config['kolab_bonnie_api'] = array(
|
||||||
'uri' => 'https://<kolab-hostname>:8080/api/rpc',
|
'uri' => 'https://<kolab-hostname>:8080/api/rpc',
|
||||||
|
|
|
@ -46,12 +46,14 @@ class kolab_storage
|
||||||
private static $ready = false;
|
private static $ready = false;
|
||||||
private static $with_tempsubs = true;
|
private static $with_tempsubs = true;
|
||||||
private static $subscriptions;
|
private static $subscriptions;
|
||||||
|
private static $ldapcache = array();
|
||||||
private static $typedata = array();
|
private static $typedata = array();
|
||||||
private static $states;
|
private static $states;
|
||||||
private static $config;
|
private static $config;
|
||||||
private static $imap;
|
private static $imap;
|
||||||
private static $ldap;
|
private static $ldap;
|
||||||
|
|
||||||
|
|
||||||
// Default folder names
|
// Default folder names
|
||||||
private static $default_folders = array(
|
private static $default_folders = array(
|
||||||
'event' => 'Calendar',
|
'event' => 'Calendar',
|
||||||
|
@ -354,7 +356,6 @@ class kolab_storage
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes IMAP folder
|
* Deletes IMAP folder
|
||||||
*
|
*
|
||||||
|
@ -421,7 +422,6 @@ class kolab_storage
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renames IMAP folder
|
* Renames IMAP folder
|
||||||
*
|
*
|
||||||
|
@ -457,7 +457,6 @@ class kolab_storage
|
||||||
return $success;
|
return $success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rename or Create a new IMAP folder.
|
* Rename or Create a new IMAP folder.
|
||||||
*
|
*
|
||||||
|
@ -552,7 +551,6 @@ class kolab_storage
|
||||||
return $result ? $folder : false;
|
return $result ? $folder : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter for human-readable name of Kolab object (folder)
|
* Getter for human-readable name of Kolab object (folder)
|
||||||
* with kolab_custom_display_names support.
|
* with kolab_custom_display_names support.
|
||||||
|
@ -637,20 +635,18 @@ class kolab_storage
|
||||||
if (!$found && !empty($namespace['other'])) {
|
if (!$found && !empty($namespace['other'])) {
|
||||||
foreach ($namespace['other'] as $ns) {
|
foreach ($namespace['other'] as $ns) {
|
||||||
if (strlen($ns[0]) && strpos($folder, $ns[0]) === 0) {
|
if (strlen($ns[0]) && strpos($folder, $ns[0]) === 0) {
|
||||||
// remove namespace prefix
|
// remove namespace prefix and extract username
|
||||||
$folder = substr($folder, strlen($ns[0]));
|
$folder = substr($folder, strlen($ns[0]));
|
||||||
$delim = $ns[1];
|
$delim = $ns[1];
|
||||||
// get username
|
|
||||||
$pos = strpos($folder, $delim);
|
|
||||||
if ($pos) {
|
|
||||||
$prefix = '('.substr($folder, 0, $pos).')';
|
|
||||||
$folder = substr($folder, $pos+1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$prefix = '('.$folder.')';
|
|
||||||
$folder = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// get username part and map it to user name
|
||||||
|
$pos = strpos($folder, $delim);
|
||||||
|
$fid = $pos ? substr($folder, 0, $pos) : $folder;
|
||||||
|
$fid = self::folder_id2user($fid, true);
|
||||||
|
$fid = str_replace($delim, '', $fid);
|
||||||
|
|
||||||
|
$prefix = "($fid)";
|
||||||
|
$folder = $pos ? substr($folder, $pos + 1) : '';
|
||||||
$found = true;
|
$found = true;
|
||||||
$folder_ns = 'other';
|
$folder_ns = 'other';
|
||||||
break;
|
break;
|
||||||
|
@ -729,7 +725,6 @@ class kolab_storage
|
||||||
return $name;
|
return $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a SELECT field with folders list
|
* Creates a SELECT field with folders list
|
||||||
*
|
*
|
||||||
|
@ -812,7 +807,6 @@ class kolab_storage
|
||||||
return $select;
|
return $select;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of folder names
|
* Returns a list of folder names
|
||||||
*
|
*
|
||||||
|
@ -976,7 +970,6 @@ class kolab_storage
|
||||||
return $folders;
|
return $folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort the given list of kolab folders by namespace/name
|
* Sort the given list of kolab folders by namespace/name
|
||||||
*
|
*
|
||||||
|
@ -1006,7 +999,6 @@ class kolab_storage
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the folder tree and add the missing parents as virtual folders
|
* Check the folder tree and add the missing parents as virtual folders
|
||||||
*
|
*
|
||||||
|
@ -1082,7 +1074,6 @@ class kolab_storage
|
||||||
return $_folders;
|
return $_folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns folder types indexed by folder name
|
* Returns folder types indexed by folder name
|
||||||
*
|
*
|
||||||
|
@ -1149,7 +1140,6 @@ class kolab_storage
|
||||||
return self::$typedata[$prefix];
|
return self::$typedata[$prefix];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for array_map to select the correct annotation value
|
* Callback for array_map to select the correct annotation value
|
||||||
*/
|
*/
|
||||||
|
@ -1165,7 +1155,6 @@ class kolab_storage
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns type of IMAP folder
|
* Returns type of IMAP folder
|
||||||
*
|
*
|
||||||
|
@ -1197,7 +1186,6 @@ class kolab_storage
|
||||||
return 'mail';
|
return 'mail';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets folder content-type.
|
* Sets folder content-type.
|
||||||
*
|
*
|
||||||
|
@ -1220,7 +1208,6 @@ class kolab_storage
|
||||||
return $success;
|
return $success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check subscription status of this folder
|
* Check subscription status of this folder
|
||||||
*
|
*
|
||||||
|
@ -1242,7 +1229,6 @@ class kolab_storage
|
||||||
($temp && in_array($folder, (array)$_SESSION['kolab_subscribed_folders']));
|
($temp && in_array($folder, (array)$_SESSION['kolab_subscribed_folders']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change subscription status of this folder
|
* Change subscription status of this folder
|
||||||
*
|
*
|
||||||
|
@ -1273,7 +1259,6 @@ class kolab_storage
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change subscription status of this folder
|
* Change subscription status of this folder
|
||||||
*
|
*
|
||||||
|
@ -1301,7 +1286,6 @@ class kolab_storage
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check activation status of this folder
|
* Check activation status of this folder
|
||||||
*
|
*
|
||||||
|
@ -1316,7 +1300,6 @@ class kolab_storage
|
||||||
return in_array($folder, $active_folders);
|
return in_array($folder, $active_folders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change activation status of this folder
|
* Change activation status of this folder
|
||||||
*
|
*
|
||||||
|
@ -1331,7 +1314,6 @@ class kolab_storage
|
||||||
return self::set_state($folder, true);
|
return self::set_state($folder, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change activation status of this folder
|
* Change activation status of this folder
|
||||||
*
|
*
|
||||||
|
@ -1347,7 +1329,6 @@ class kolab_storage
|
||||||
return self::set_state($folder, false);
|
return self::set_state($folder, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return list of active folders
|
* Return list of active folders
|
||||||
*/
|
*/
|
||||||
|
@ -1379,7 +1360,6 @@ class kolab_storage
|
||||||
return self::$states;
|
return self::$states;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update list of active folders
|
* Update list of active folders
|
||||||
*/
|
*/
|
||||||
|
@ -1504,7 +1484,6 @@ class kolab_storage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param mixed $query Search value (or array of field => value pairs)
|
* @param mixed $query Search value (or array of field => value pairs)
|
||||||
|
@ -1544,7 +1523,6 @@ class kolab_storage
|
||||||
return $results;
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of IMAP folders shared by the given user
|
* Returns a list of IMAP folders shared by the given user
|
||||||
*
|
*
|
||||||
|
@ -1584,7 +1562,6 @@ class kolab_storage
|
||||||
return $folders;
|
return $folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of (virtual) top-level folders from the other users namespace
|
* Get a list of (virtual) top-level folders from the other users namespace
|
||||||
*
|
*
|
||||||
|
@ -1635,7 +1612,6 @@ class kolab_storage
|
||||||
return $folders;
|
return $folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for user_delete plugin hooks
|
* Handler for user_delete plugin hooks
|
||||||
*
|
*
|
||||||
|
@ -1673,4 +1649,79 @@ class kolab_storage
|
||||||
return $metadata[$folder];
|
return $metadata[$folder];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get user attributes for specified other user (imap) folder identifier.
|
||||||
|
* Note: This uses LDAP config/code from kolab_auth.
|
||||||
|
*
|
||||||
|
* @param string $folder_id Folder name w/o path (imap user identifier)
|
||||||
|
* @param bool $as_string Return configured display name attribute value
|
||||||
|
*
|
||||||
|
* @return array User attributes
|
||||||
|
* @see self::ldap()
|
||||||
|
*/
|
||||||
|
public static function folder_id2user($folder_id, $as_string = false)
|
||||||
|
{
|
||||||
|
static $domain, $cache, $name_attr;
|
||||||
|
|
||||||
|
$rcube = rcube::get_instance();
|
||||||
|
|
||||||
|
if ($domain === null) {
|
||||||
|
list(, $domain) = explode('@', $rcube->get_user_name());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($name_attr === null) {
|
||||||
|
$name_attr = (array) (self::$config->get('kolab_users_name_field', self::$config->get('kolab_auth_name')) ?: 'name');
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = $folder_id;
|
||||||
|
if ($domain && strpos($find, '@') === false) {
|
||||||
|
$token .= '@' . $domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($cache === null) {
|
||||||
|
$cache = $rcube->get_cache_shared('kolab_users') ?: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use value cached in memory for repeated lookups
|
||||||
|
if (!$cache && array_key_exists($token, self::$ldapcache)) {
|
||||||
|
$user = self::$ldapcache[$token];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($user) && $cache) {
|
||||||
|
$user = $cache->get($token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($user) && ($ldap = kolab_storage::ldap())) {
|
||||||
|
$user = $ldap->get_user_record($token, $_SESSION['imap_host']);
|
||||||
|
|
||||||
|
if (!empty($user)) {
|
||||||
|
$keys = array('displayname', 'name', 'mail'); // supported keys
|
||||||
|
$user = array_intersect_key($user, array_flip($keys));
|
||||||
|
|
||||||
|
if (!empty($user)) {
|
||||||
|
if ($cache) {
|
||||||
|
$cache->set($token, $user);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self::$ldapcache[$token] = $user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($user)) {
|
||||||
|
if ($as_string) {
|
||||||
|
foreach ($name_attr as $attr) {
|
||||||
|
if ($name = $user[$attr]) {
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $user['displayname'] ?: $user['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
*/
|
*/
|
||||||
class kolab_storage_folder_user extends kolab_storage_folder_virtual
|
class kolab_storage_folder_user extends kolab_storage_folder_virtual
|
||||||
{
|
{
|
||||||
protected static $ldapcache = array();
|
|
||||||
|
|
||||||
public $ldaprec;
|
public $ldaprec;
|
||||||
public $type;
|
public $type;
|
||||||
|
|
||||||
|
@ -36,21 +34,13 @@ class kolab_storage_folder_user extends kolab_storage_folder_virtual
|
||||||
parent::__construct($name, kolab_storage::object_prettyname($name), 'other', $parent);
|
parent::__construct($name, kolab_storage::object_prettyname($name), 'other', $parent);
|
||||||
|
|
||||||
if (!empty($ldaprec)) {
|
if (!empty($ldaprec)) {
|
||||||
self::$ldapcache[$name] = $this->ldaprec = $ldaprec;
|
$this->ldaprec = $ldaprec;
|
||||||
}
|
}
|
||||||
// use value cached in memory for repeated lookups
|
else {
|
||||||
else if (array_key_exists($name, self::$ldapcache)) {
|
$this->ldaprec = kolab_storage::folder_id2user(parent::get_foldername($this->name));
|
||||||
$this->ldaprec = self::$ldapcache[$name];
|
|
||||||
}
|
|
||||||
// lookup user in LDAP and set $this->ldaprec
|
|
||||||
else if ($ldap = kolab_storage::ldap()) {
|
|
||||||
// get domain from current user
|
|
||||||
list(,$domain) = explode('@', rcube::get_instance()->get_user_name());
|
|
||||||
$this->ldaprec = $ldap->get_user_record(parent::get_foldername($this->name) . '@' . $domain, $_SESSION['imap_host']);
|
|
||||||
if (!empty($this->ldaprec)) {
|
if (!empty($this->ldaprec)) {
|
||||||
$this->ldaprec['kolabtargetfolder'] = $name;
|
$this->ldaprec['kolabtargetfolder'] = $name;
|
||||||
}
|
}
|
||||||
self::$ldapcache[$name] = $this->ldaprec;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue