[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Copyright 2012-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 2012-2014 Horde LLC 10 * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 11 * @package Imap_Client 12 */ 13 14 /** 15 * An object implementing lookups between UIDs and message sequence numbers. 16 * 17 * @author Michael Slusarz <slusarz@horde.org> 18 * @category Horde 19 * @copyright 2012-2014 Horde LLC 20 * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 21 * @package Imap_Client 22 * @since 2.1.0 23 * 24 * @property-read array $map The raw ID mapping data. 25 * @property-read Horde_Imap_Client_Ids $seq The sorted sequence values. 26 * @property-read Horde_Imap_Client_Ids $uids The sorted UIDs. 27 */ 28 class Horde_Imap_Client_Ids_Map implements Countable, IteratorAggregate, Serializable 29 { 30 /** 31 * Sequence -> UID mapping. 32 * 33 * @var array 34 */ 35 protected $_ids = array(); 36 37 /** 38 * Is the array sorted? 39 * 40 * @var boolean 41 */ 42 protected $_sorted = true; 43 44 /** 45 * Constructor. 46 * 47 * @param array $ids Array of sequence -> UID mapping. 48 */ 49 public function __construct(array $ids = array()) 50 { 51 $this->update($ids); 52 } 53 54 /** 55 */ 56 public function __get($name) 57 { 58 switch ($name) { 59 case 'map': 60 return $this->_ids; 61 62 case 'seq': 63 $this->sort(); 64 return new Horde_Imap_Client_Ids(array_keys($this->_ids), true); 65 66 case 'uids': 67 $this->sort(); 68 return new Horde_Imap_Client_Ids($this->_ids); 69 } 70 } 71 72 /** 73 * Updates the mapping. 74 * 75 * @param array $ids Array of sequence -> UID mapping. 76 * 77 * @return boolean True if the mapping changed. 78 */ 79 public function update($ids) 80 { 81 if (empty($ids)) { 82 return false; 83 } elseif (empty($this->_ids)) { 84 $this->_ids = $ids; 85 $change = true; 86 } else { 87 $change = false; 88 foreach ($ids as $k => $v) { 89 if (!isset($this->_ids[$k]) || ($this->_ids[$k] != $v)) { 90 $this->_ids[$k] = $v; 91 $change = true; 92 } 93 } 94 } 95 96 if ($change) { 97 $this->_sorted = false; 98 } 99 100 return $change; 101 } 102 103 /** 104 * Create a Sequence <-> UID lookup table. 105 * 106 * @param Horde_Imap_Client_Ids $ids IDs to lookup. 107 * 108 * @return array Keys are sequence numbers, values are UIDs. 109 */ 110 public function lookup(Horde_Imap_Client_Ids $ids) 111 { 112 if ($ids->all) { 113 return $this->_ids; 114 } elseif ($ids->sequence) { 115 return array_intersect_key($this->_ids, array_flip($ids->ids)); 116 } 117 118 return array_intersect($this->_ids, $ids->ids); 119 } 120 121 /** 122 * Removes messages from the ID mapping. 123 * 124 * @param Horde_Imap_Client_Ids $ids IDs to remove. 125 */ 126 public function remove(Horde_Imap_Client_Ids $ids) 127 { 128 /* For sequence numbers, we need to reindex anytime we have an index 129 * that appears equal to or after a previously seen index. If an IMAP 130 * server is smart, it will expunge in reverse order instead. */ 131 if ($ids->sequence) { 132 $remove = $ids->ids; 133 } else { 134 $ids->sort(); 135 $remove = array_reverse(array_keys($this->lookup($ids))); 136 } 137 138 if (empty($remove)) { 139 return; 140 } 141 142 $this->sort(); 143 144 /* Find the minimum sequence number to remove. We know entries before 145 * this are untouched so no need to process them multiple times. */ 146 $first = min($remove); 147 $edit = $newids = array(); 148 foreach (array_keys($this->_ids) as $i => $seq) { 149 if ($seq >= $first) { 150 $i += (($seq == $first) ? 0 : 1); 151 $newids = array_slice($this->_ids, 0, $i, true); 152 $edit = array_slice($this->_ids, $i + (($seq == $first) ? 0 : 1), null, true); 153 break; 154 } 155 } 156 157 if (!empty($edit)) { 158 foreach ($remove as $val) { 159 $found = false; 160 $tmp = array(); 161 162 foreach (array_keys($edit) as $i => $seq) { 163 if ($found) { 164 $tmp[$seq - 1] = $edit[$seq]; 165 } elseif ($seq >= $val) { 166 $tmp = array_slice($edit, 0, ($seq == $val) ? $i : $i + 1, true); 167 $found = true; 168 } 169 } 170 171 $edit = $tmp; 172 } 173 } 174 175 $this->_ids = $newids + $edit; 176 } 177 178 /** 179 * Sort the map. 180 */ 181 public function sort() 182 { 183 if (!$this->_sorted) { 184 ksort($this->_ids, SORT_NUMERIC); 185 $this->_sorted = true; 186 } 187 } 188 189 /* Countable methods. */ 190 191 /** 192 */ 193 public function count() 194 { 195 return count($this->_ids); 196 } 197 198 /* IteratorAggregate method. */ 199 200 /** 201 */ 202 public function getIterator() 203 { 204 return new ArrayIterator($this->_ids); 205 } 206 207 /* Serializable methods. */ 208 209 /** 210 */ 211 public function serialize() 212 { 213 /* Sort before storing; provides more compressible representation. */ 214 $this->sort(); 215 216 return json_encode(array( 217 strval(new Horde_Imap_Client_Ids(array_keys($this->_ids))), 218 strval(new Horde_Imap_Client_Ids(array_values($this->_ids))) 219 )); 220 } 221 222 /** 223 */ 224 public function unserialize($data) 225 { 226 $data = json_decode($data, true); 227 228 $keys = new Horde_Imap_Client_Ids($data[0]); 229 $vals = new Horde_Imap_Client_Ids($data[1]); 230 $this->_ids = array_combine($keys->ids, $vals->ids); 231 232 /* Guaranteed to be sorted if unserializing. */ 233 $this->_sorted = true; 234 } 235 236 }
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 |