[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Copyright 2013-2014 Horde LLC (http://www.horde.org/) 4 * 5 * See the enclosed file COPYING for license information (LGPL). If you 6 * did not receive this file, see http://www.horde.org/licenses/lgpl21. 7 * 8 * @category Horde 9 * @copyright 2013-2014 Horde LLC 10 * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 11 * @package Imap_Client 12 */ 13 14 /** 15 * A MongoDB database implementation for caching IMAP/POP data. 16 * Requires the Horde_Mongo class. 17 * 18 * @author Michael Slusarz <slusarz@horde.org> 19 * @category Horde 20 * @copyright 2013-2014 Horde LLC 21 * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 22 * @package Imap_Client 23 */ 24 class Horde_Imap_Client_Cache_Backend_Mongo extends Horde_Imap_Client_Cache_Backend implements Horde_Mongo_Collection_Index 25 { 26 /** Mongo collection names. */ 27 const BASE = 'horde_imap_client_cache_data'; 28 const MD = 'horde_imap_client_cache_metadata'; 29 const MSG = 'horde_imap_client_cache_message'; 30 31 /** Mongo field names: BASE collection. */ 32 const BASE_HOSTSPEC = 'hostspec'; 33 const BASE_MAILBOX = 'mailbox'; 34 const BASE_MODIFIED = 'modified'; 35 const BASE_PORT = 'port'; 36 const BASE_UID = 'data'; 37 const BASE_USERNAME = 'username'; 38 39 /** Mongo field names: MD collection. */ 40 const MD_DATA = 'data'; 41 const MD_FIELD = 'field'; 42 const MD_UID = 'uid'; 43 44 /** Mongo field names: MSG collection. */ 45 const MSG_DATA = 'data'; 46 const MSG_MSGUID = 'msguid'; 47 const MSG_UID = 'uid'; 48 49 /** 50 * The MongoDB object for the cache data. 51 * 52 * @var MongoDB 53 */ 54 protected $_db; 55 56 /** 57 * The list of indices. 58 * 59 * @var array 60 */ 61 protected $_indices = array( 62 self::BASE => array( 63 'base_index_1' => array( 64 self::BASE_HOSTSPEC => 1, 65 self::BASE_MAILBOX => 1, 66 self::BASE_PORT => 1, 67 self::BASE_USERNAME => 1, 68 ) 69 ), 70 self::MSG => array( 71 'msg_index_1' => array( 72 self::MSG_MSGUID => 1, 73 self::MSG_UID => 1 74 ) 75 ) 76 ); 77 78 /** 79 * Constructor. 80 * 81 * @param array $params Configuration parameters: 82 * <pre> 83 * - REQUIRED parameters: 84 * - mongo_db: (Horde_Mongo_Client) A MongoDB client object. 85 * </pre> 86 */ 87 public function __construct(array $params = array()) 88 { 89 if (!isset($params['mongo_db'])) { 90 throw new InvalidArgumentException('Missing mongo_db parameter.'); 91 } 92 93 parent::__construct($params); 94 } 95 96 /** 97 */ 98 protected function _initOb() 99 { 100 $this->_db = $this->_params['mongo_db']->selectDB(null); 101 } 102 103 /** 104 */ 105 public function get($mailbox, $uids, $fields, $uidvalid) 106 { 107 $this->getMetaData($mailbox, $uidvalid, array('uidvalid')); 108 109 if (!($uid = $this->_getUid($mailbox))) { 110 return array(); 111 } 112 113 $out = array(); 114 $query = array( 115 self::MSG_MSGUID => array('$in' => array_map('strval', $uids)), 116 self::MSG_UID => $uid 117 ); 118 119 try { 120 $cursor = $this->_db->selectCollection(self::MSG)->find( 121 $query, 122 array( 123 self::MSG_DATA => true, 124 self::MSG_MSGUID => true 125 ) 126 ); 127 foreach ($cursor as $val) { 128 $out[$val[self::MSG_MSGUID]] = $this->_value($val[self::MSG_DATA]); 129 } 130 } catch (MongoException $e) {} 131 132 return $out; 133 } 134 135 /** 136 */ 137 public function getCachedUids($mailbox, $uidvalid) 138 { 139 $this->getMetaData($mailbox, $uidvalid, array('uidvalid')); 140 141 if (!($uid = $this->_getUid($mailbox))) { 142 return array(); 143 } 144 145 $out = array(); 146 $query = array( 147 self::MSG_UID => $uid 148 ); 149 150 try { 151 $cursor = $this->_db->selectCollection(self::MSG)->find( 152 $query, 153 array( 154 self::MSG_MSGUID => true 155 ) 156 ); 157 foreach ($cursor as $val) { 158 $out[] = $val[self::MSG_MSGUID]; 159 } 160 } catch (MongoException $e) {} 161 162 return $out; 163 } 164 165 /** 166 */ 167 public function set($mailbox, $data, $uidvalid) 168 { 169 if ($uid = $this->_getUid($mailbox)) { 170 $res = $this->get($mailbox, array_keys($data), array(), $uidvalid); 171 } else { 172 $res = array(); 173 $uid = $this->_createUid($mailbox); 174 } 175 176 $coll = $this->_db->selectCollection(self::MSG); 177 178 foreach ($data as $key => $val) { 179 try { 180 if (isset($res[$key])) { 181 $coll->update(array( 182 self::MSG_MSGUID => strval($key), 183 self::MSG_UID => $uid 184 ), array( 185 self::MSG_DATA => $this->_value(array_merge($res[$key], $val)), 186 self::MSG_MSGUID => strval($key), 187 self::MSG_UID => $uid 188 )); 189 } else { 190 $coll->insert(array( 191 self::MSG_DATA => $this->_value($val), 192 self::MSG_MSGUID => strval($key), 193 self::MSG_UID => $uid 194 )); 195 } 196 } catch (MongoException $e) {} 197 } 198 199 /* Update modified time. */ 200 try { 201 $this->_db->selectCollection(self::BASE)->update( 202 array(self::BASE_UID => $uid), 203 array(self::BASE_MODIFIED => time()) 204 ); 205 } catch (MongoException $e) {} 206 207 /* Update uidvalidity. */ 208 $this->setMetaData($mailbox, array('uidvalid' => $uidvalid)); 209 } 210 211 /** 212 */ 213 public function getMetaData($mailbox, $uidvalid, $entries) 214 { 215 if (!($uid = $this->_getUid($mailbox))) { 216 return array(); 217 } 218 219 $out = array(); 220 $query = array( 221 self::MD_UID => $uid 222 ); 223 224 if (!empty($entries)) { 225 $entries[] = 'uidvalid'; 226 $query[self::MD_FIELD] = array( 227 '$in' => array_unique($entries) 228 ); 229 } 230 231 try { 232 $cursor = $this->_db->selectCollection(self::MD)->find( 233 $query, 234 array( 235 self::MD_DATA => true, 236 self::MD_FIELD => true 237 ) 238 ); 239 foreach ($cursor as $val) { 240 $out[$val[self::MD_FIELD]] = $this->_value($val[self::MD_DATA]); 241 } 242 243 if (is_null($uidvalid) || 244 !isset($out['uidvalid']) || 245 ($out['uidvalid'] == $uidvalid)) { 246 return $out; 247 } 248 249 $this->deleteMailbox($mailbox); 250 } catch (MongoException $e) {} 251 252 return array(); 253 } 254 255 /** 256 */ 257 public function setMetaData($mailbox, $data) 258 { 259 if (!($uid = $this->_getUid($mailbox))) { 260 $uid = $this->_createUid($mailbox); 261 } 262 263 $coll = $this->_db->selectCollection(self::MD); 264 265 foreach ($data as $key => $val) { 266 try { 267 $coll->update( 268 array( 269 self::MD_FIELD => $key, 270 self::MD_UID => $uid 271 ), 272 array( 273 self::MD_DATA => $this->_value($val), 274 self::MD_FIELD => $key, 275 self::MD_UID => $uid 276 ), 277 array('upsert' => true) 278 ); 279 } catch (MongoException $e) {} 280 } 281 } 282 283 /** 284 */ 285 public function deleteMsgs($mailbox, $uids) 286 { 287 if (!empty($uids) && ($uid = $this->_getUid($mailbox))) { 288 try { 289 $this->_db->selectCollection(self::MSG)->remove(array( 290 self::MSG_MSGUID => array('$in' => array_map('strval', $uids)), 291 self::MSG_UID => $uid 292 )); 293 } catch (MongoException $e) {} 294 } 295 } 296 297 /** 298 */ 299 public function deleteMailbox($mailbox) 300 { 301 if (!($uid = $this->_getUid($mailbox))) { 302 return; 303 } 304 305 foreach (array(self::BASE, self::MD, self::MSG) as $val) { 306 try { 307 $this->_db->selectCollection($val)->remove(array( 308 'uid' => $uid 309 )); 310 } catch (MongoException $e) {} 311 } 312 } 313 314 /** 315 */ 316 public function clear($lifetime) 317 { 318 if (is_null($lifetime)) { 319 foreach (array(self::BASE, self::MD, self::MSG) as $val) { 320 $this->_db->selectCollection($val)->drop(); 321 } 322 return; 323 } 324 325 $query = array( 326 self::BASE_MODIFIED => array('$lt' => (time() - $lifetime)) 327 ); 328 $uids = array(); 329 330 try { 331 $cursor = $this->_db->selectCollection(self::BASE)->find($query); 332 foreach ($cursor as $val) { 333 $uids[] = strval($val['_id']); 334 } 335 } catch (MongoException $e) {} 336 337 if (empty($uids)) { 338 return; 339 } 340 341 foreach (array(self::BASE, self::MD, self::MSG) as $val) { 342 try { 343 $this->_db->selectCollection($val)->remove(array( 344 'uid' => array('$in' => $uids) 345 )); 346 } catch (MongoException $e) {} 347 } 348 } 349 350 /** 351 * Return the UID for a mailbox/user/server combo. 352 * 353 * @param string $mailbox Mailbox name. 354 * 355 * @return string UID from base table. 356 */ 357 protected function _getUid($mailbox) 358 { 359 $query = array( 360 self::BASE_HOSTSPEC => $this->_params['hostspec'], 361 self::BASE_MAILBOX => $mailbox, 362 self::BASE_PORT => $this->_params['port'], 363 self::BASE_USERNAME => $this->_params['username'] 364 ); 365 366 try { 367 if ($result = $this->_db->selectCollection(self::BASE)->findOne($query)) { 368 return strval($result['_id']); 369 } 370 } catch (MongoException $e) {} 371 372 return null; 373 } 374 375 /** 376 * Create and return the UID for a mailbox/user/server combo. 377 * 378 * @param string $mailbox Mailbox name. 379 * 380 * @return string UID from base table. 381 */ 382 protected function _createUid($mailbox) 383 { 384 $this->_db->selectCollection(self::BASE)->insert(array( 385 self::BASE_HOSTSPEC => $this->_params['hostspec'], 386 self::BASE_MAILBOX => $mailbox, 387 self::BASE_PORT => $this->_params['port'], 388 self::BASE_USERNAME => $this->_params['username'] 389 )); 390 391 return $this->_getUid($mailbox); 392 } 393 394 /** 395 * Convert data from/to storage format. 396 * 397 * @param mixed|MongoBinData $data The data object. 398 * 399 * @return mixed|MongoBinData The converted data. 400 */ 401 protected function _value($data) 402 { 403 static $compress; 404 405 if (!isset($compress)) { 406 $compress = new Horde_Compress_Fast(); 407 } 408 409 return ($data instanceof MongoBinData) 410 ? @unserialize($compress->decompress($data->bin)) 411 : new MongoBinData($compress->compress(serialize($data)), MongoBinData::BYTE_ARRAY); 412 } 413 414 /* Horde_Mongo_Collection_Index methods. */ 415 416 /** 417 */ 418 public function checkMongoIndices() 419 { 420 foreach ($this->_indices as $key => $val) { 421 if (!$this->_params['mongo_db']->checkIndices($key, $val)) { 422 return false; 423 } 424 } 425 426 return true; 427 } 428 429 /** 430 */ 431 public function createMongoIndices() 432 { 433 foreach ($this->_indices as $key => $val) { 434 $this->_params['mongo_db']->createIndices($key, $val); 435 } 436 } 437 438 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |