Skip to content

Commit

Permalink
Cleanup caching of namespace information
Browse files Browse the repository at this point in the history
Namespace information is backend-specific, not mailbox-specific, so
that's the best place to cache.

Merge defaultNamespace() into getNamespace().

Extend the base imap client's getNamespaces() instead of creating
entirely separate method.
  • Loading branch information
slusarz committed Nov 27, 2013
1 parent aa981af commit 6ceb6e9
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 98 deletions.
2 changes: 1 addition & 1 deletion imp/lib/Ftree/Account/Imap.php
Expand Up @@ -49,7 +49,7 @@ public function getList($query = null)
$unsub = false;

if (is_integer($query)) {
$ns = $imp_imap->getNamespaceList();
$ns = $imp_imap->getNamespaces();

if ($query & self::INIT) {
/* Add namespace elements. */
Expand Down
71 changes: 29 additions & 42 deletions imp/lib/Imap.php
Expand Up @@ -52,6 +52,9 @@ class IMP_Imap implements Serializable
const ACCESS_DRAFTS = 11;
const ACCESS_REMOTE = 12;

/* Default namespace. */
const NS_DEFAULT = "\0default";

/**
* Cached backend configuration.
*
Expand Down Expand Up @@ -275,7 +278,6 @@ public function createImapObject($config, $imap = true)
'lang' => $sconfig->lang,
'timeout' => $sconfig->timeout,
// 'imp:login' - Set in __call()
// 'imp:nsdefault' - Set in defaultNamespace()
), $config);

try {
Expand Down Expand Up @@ -423,14 +425,20 @@ public function accessCompose($right, $email_count)
*
* @return array See Horde_Imap_Client_Base#getNamespaces().
*/
public function getNamespaceList()
public function getNamespaces()
{
try {
$ns = $this->config->namespace;
return $this->getNamespaces(is_null($ns) ? array() : $ns);
} catch (Horde_Imap_Client_Exception $e) {
return array();
if (!isset($this->_temp['ns'])) {
try {
$nsconfig = $this->config->namespace;
$this->_temp['ns'] = $this->__call('getNamespaces', array(
is_null($nsconfig) ? array() : $nsconfig
));
} catch (Horde_Imap_Client_Exception $e) {
return array();
}
}

return $this->_temp['ns'];
}

/**
Expand All @@ -443,23 +451,28 @@ public function getNamespaceList()
* @return mixed The namespace info for the mailbox path or null if the
* path doesn't exist.
*/
public function getNamespace($mailbox = null, $personal = false)
public function getNamespace($mailbox, $personal = false)
{
if (!$this->isImap($mailbox)) {
if (!$this->isImap() || !$this->_ob->getParam('imp:login')) {
return null;
}

$ns = $this->getNamespaceList();
$ns = $this->getNamespaces();

if (is_null($mailbox)) {
reset($ns);
$mailbox = key($ns);
if (isset($ns[$mailbox])) {
return $ns[$mailbox];
}

foreach ($ns as $key => $val) {
$mbox = $mailbox . $val['delimiter'];
if (strlen($key) && (strpos($mbox, $key) === 0)) {
return $val;
if ($mailbox === self::NS_DEFAULT) {
if ($val['type'] === Horde_Imap_Client::NS_PERSONAL) {
return $val;
}
} else {
$mbox = $mailbox . $val['delimiter'];
if (strlen($key) && (strpos($mbox, $key) === 0)) {
return $val;
}
}
}

Expand All @@ -468,32 +481,6 @@ public function getNamespace($mailbox = null, $personal = false)
: null;
}

/**
* Get the default personal namespace.
*
* @return mixed The default personal namespace info.
*/
public function defaultNamespace()
{
if (!$this->init ||
!$this->isImap() ||
!$this->_ob->getParam('imp:login')) {
return null;
}

if (is_null($ns = $this->_ob->getParam('imp:nsdefault'))) {
foreach ($this->getNamespaceList() as $val) {
if ($val['type'] == Horde_Imap_Client::NS_PERSONAL) {
$this->_ob->setParam('imp:nsdefault', $val);
$this->_changed = true;
return $val;
}
}
}

return $ns;
}

/**
* Return the cache ID for this mailbox.
*
Expand Down
68 changes: 14 additions & 54 deletions imp/lib/Mailbox.php
Expand Up @@ -181,15 +181,11 @@ class IMP_Mailbox implements Serializable
const CACHE_ICONS = 'i';
// (string) Label string
const CACHE_LABEL = 'l';
// (array) Namespace information
const CACHE_NAMESPACE = 'n';
// (integer) UIDVALIDITY
const CACHE_UIDVALIDITY = 'v';

/* Cache identifiers - temporary data. */
const CACHE_ICONHOOK = 'ic';
const CACHE_NSDEFAULT = 'nd';
const CACHE_NSEMPTY = 'ne';
const CACHE_PREFTO = 'pt';
const CACHE_SPECIALMBOXES = 's';

Expand Down Expand Up @@ -534,7 +530,7 @@ public function __get($key)

case 'namespace_append':
$imp_imap = $this->imp_imap;
$def_ns = $imp_imap->defaultNamespace();
$def_ns = $imp_imap->getNamespace($imp_imap::NS_DEFAULT);
if (is_null($def_ns)) {
return $this;
}
Expand Down Expand Up @@ -564,41 +560,7 @@ public function __get($key)
: $ns_info['delimiter'];

case 'namespace_info':
$keys = array('delimiter', 'hidden', 'name', 'translation', 'type');

if (isset($this->_cache[self::CACHE_NAMESPACE])) {
$ns = $this->_cache[self::CACHE_NAMESPACE];

if (is_null($ns)) {
return null;
}

$ret = array();
foreach ($keys as $key => $val) {
$ret[$val] = isset($ns[$key])
? $ns[$key]
: '';
}

return $ret;
}

$ns_info = $this->imp_imap->getNamespace(strlen($this) ? $this->_mbox : null);
if (is_null($ns_info)) {
$this->_cache[self::CACHE_NAMESPACE] = null;
} else {
/* Store data compressed in the cache array. */
$this->_cache[self::CACHE_NAMESPACE] = array();
foreach ($keys as $id => $key) {
if ($ns_info[$key]) {
$this->_cache[self::CACHE_NAMESPACE][$id] = $ns_info[$key];
}
}
}

$this->_changed = self::CHANGED_YES;

return $ns_info;
return $this->imp_imap->getNamespace(strlen($this) ? $this->_mbox : IMP_Imap::NS_DEFAULT);

case 'nonimap':
return ($this->search ||
Expand Down Expand Up @@ -1536,20 +1498,16 @@ static public function prefFrom($mbox)
{
$imp_imap = $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create();

if (!isset(self::$_temp[self::CACHE_NSDEFAULT])) {
self::$_temp[self::CACHE_NSDEFAULT] = $imp_imap->defaultNamespace();
self::$_temp[self::CACHE_NSEMPTY] = $imp_imap->getNamespace('');
}

$empty_ns = self::$_temp[self::CACHE_NSEMPTY];
$empty_ns = $imp_imap->getNamespace('');

if (!is_null($empty_ns) &&
(strpos($mbox, $empty_ns['delimiter']) === 0)) {
/* Prefixed with delimiter => from empty namespace. */
return substr($mbox, strlen($empty_ns['delimiter']));
} elseif ($imp_imap->getNamespace($mbox, true) === null) {
/* No namespace prefix => from personal namespace. */
return self::$_temp[self::CACHE_NSDEFAULT]['name'] . $mbox;
$def_ns = $imp_imap->getNamespace($imp_imap::NS_DEFAULT);
return $def_ns['name'] . $mbox;
}

return $mbox;
Expand All @@ -1564,17 +1522,19 @@ static public function prefFrom($mbox)
*/
static public function prefTo($mbox)
{
$imp_imap = $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create();
$def_ns = $imp_imap->defaultNamespace();
$empty_ns = $imp_imap->getNamespace('');

if (($ns = self::get($mbox)->namespace_info) !== null) {
$imp_imap = $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create();
$def_ns = $imp_imap->getNamespace($imp_imap::NS_DEFAULT);

if ($ns['name'] == $def_ns['name']) {
/* From personal namespace => strip namespace. */
return substr($mbox, strlen($def_ns['name']));
} elseif ($ns['name'] == $empty_ns['name']) {
/* From empty namespace => prefix with delimiter. */
return $empty_ns['delimiter'] . $mbox;
} else {
$empty_ns = $imp_imap->getNamespace('');
if ($ns['name'] == $empty_ns['name']) {
/* From empty namespace => prefix with delimiter. */
return $empty_ns['delimiter'] . $mbox;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion imp/rss.php
Expand Up @@ -37,7 +37,7 @@
if (!empty($request)) {
$request_parts = explode('/-/', $request);
if (!empty($request_parts[0])) {
$ns_info = $mailbox->imp_imap->getNamespace();
$ns_info = $mailbox->imp_imap->getNamespace(IMP_Imap::NS_DEFAULT);
$mailbox = IMP_Mailbox::get(preg_replace('/\//', $ns_info['delimiter'], trim($request_parts[0], '/')))->namespace_append;

/* Make sure mailbox exists or else exit immediately. */
Expand Down

0 comments on commit 6ceb6e9

Please sign in to comment.