[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Copyright 2011-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 2011-2014 Horde LLC 10 * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 11 * @package Imap_Client 12 */ 13 14 /** 15 * An object that provides a way to identify a list of IMAP indices. 16 * 17 * @author Michael Slusarz <slusarz@horde.org> 18 * @category Horde 19 * @copyright 2011-2014 Horde LLC 20 * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 21 * @package Imap_Client 22 * 23 * @property-read boolean $all Does this represent an ALL message set? 24 * @property-read array $ids The list of IDs. 25 * @property-read boolean $largest Does this represent the largest ID in use? 26 * @property-read string $max The largest ID (@since 2.20.0). 27 * @property-read string $min The smallest ID (@since 2.20.0). 28 * @property-read string $range_string Generates a range string consisting of 29 * all messages between begin and end of 30 * ID list. 31 * @property-read boolean $search_res Does this represent a search result? 32 * @property-read boolean $sequence Are these sequence IDs? If false, these 33 * are UIDs. 34 * @property-read boolean $special True if this is a "special" ID 35 * representation. 36 * @property-read string $tostring Return the non-sorted string 37 * representation. 38 * @property-read string $tostring_sort Return the sorted string 39 * representation. 40 */ 41 class Horde_Imap_Client_Ids implements Countable, Iterator, Serializable 42 { 43 /** 44 * "Special" representation constants. 45 */ 46 const ALL = "\01"; 47 const SEARCH_RES = "\02"; 48 const LARGEST = "\03"; 49 50 /** 51 * Allow duplicate IDs? 52 * 53 * @var boolean 54 */ 55 public $duplicates = false; 56 57 /** 58 * List of IDs. 59 * 60 * @var mixed 61 */ 62 protected $_ids = array(); 63 64 /** 65 * Are IDs message sequence numbers? 66 * 67 * @var boolean 68 */ 69 protected $_sequence = false; 70 71 /** 72 * Are IDs sorted? 73 * 74 * @var boolean 75 */ 76 protected $_sorted = false; 77 78 /** 79 * Constructor. 80 * 81 * @param mixed $ids See self::add(). 82 * @param boolean $sequence Are $ids message sequence numbers? 83 */ 84 public function __construct($ids = null, $sequence = false) 85 { 86 $this->add($ids); 87 $this->_sequence = $sequence; 88 } 89 90 /** 91 */ 92 public function __get($name) 93 { 94 switch ($name) { 95 case 'all': 96 return ($this->_ids === self::ALL); 97 98 case 'ids': 99 return is_array($this->_ids) 100 ? $this->_ids 101 : array(); 102 103 case 'largest': 104 return ($this->_ids === self::LARGEST); 105 106 case 'max': 107 $this->sort(); 108 return end($this->_ids); 109 110 case 'min': 111 $this->sort(); 112 return reset($this->_ids); 113 114 case 'range_string': 115 if (!count($this)) { 116 return ''; 117 } 118 119 $min = $this->min; 120 $max = $this->max; 121 122 return ($min == $max) 123 ? $min 124 : $min . ':' . $max; 125 126 case 'search_res': 127 return ($this->_ids === self::SEARCH_RES); 128 129 case 'sequence': 130 return (bool)$this->_sequence; 131 132 case 'special': 133 return is_string($this->_ids); 134 135 case 'tostring': 136 case 'tostring_sort': 137 if ($this->all) { 138 return '1:*'; 139 } elseif ($this->largest) { 140 return '*'; 141 } elseif ($this->search_res) { 142 return '$'; 143 } 144 return strval($this->_toSequenceString($name == 'tostring_sort')); 145 } 146 } 147 148 /** 149 */ 150 public function __toString() 151 { 152 return $this->tostring; 153 } 154 155 /** 156 * Add IDs to the current object. 157 * 158 * @param mixed $ids Either self::ALL, self::SEARCH_RES, self::LARGEST, 159 * Horde_Imap_Client_Ids object, array, or sequence 160 * string. 161 */ 162 public function add($ids) 163 { 164 if (!is_null($ids)) { 165 if (is_string($ids) && 166 in_array($ids, array(self::ALL, self::SEARCH_RES, self::LARGEST))) { 167 $this->_ids = $ids; 168 } elseif ($add = $this->_resolveIds($ids)) { 169 if (is_array($this->_ids) && !empty($this->_ids)) { 170 foreach ($add as $val) { 171 $this->_ids[] = $val; 172 } 173 } else { 174 $this->_ids = $add; 175 } 176 if (!$this->duplicates) { 177 $this->_ids = (count($this->_ids) > 25000) 178 ? array_unique($this->_ids) 179 : array_keys(array_flip($this->_ids)); 180 } 181 } 182 183 $this->_sorted = (count($this->_ids) === 1); 184 } 185 } 186 187 /** 188 * Removed IDs from the current object. 189 * 190 * @since 2.17.0 191 * 192 * @param mixed $ids Either Horde_Imap_Client_Ids object, array, or 193 * sequence string. 194 */ 195 public function remove($ids) 196 { 197 if (!$this->isEmpty() && 198 ($remove = $this->_resolveIds($ids))) { 199 $this->_ids = array_diff($this->_ids, array_unique($remove)); 200 } 201 } 202 203 /** 204 * Is this object empty (i.e. does not contain IDs)? 205 * 206 * @return boolean True if object is empty. 207 */ 208 public function isEmpty() 209 { 210 return (is_array($this->_ids) && !count($this->_ids)); 211 } 212 213 /** 214 * Reverses the order of the IDs. 215 */ 216 public function reverse() 217 { 218 if (is_array($this->_ids)) { 219 $this->_ids = array_reverse($this->_ids); 220 } 221 } 222 223 /** 224 * Sorts the IDs numerically. 225 */ 226 public function sort() 227 { 228 if (!$this->_sorted && is_array($this->_ids)) { 229 sort($this->_ids, SORT_NUMERIC); 230 $this->_sorted = true; 231 } 232 } 233 234 /** 235 * Split the sequence string at an approximate length. 236 * 237 * @since 2.7.0 238 * 239 * @param integer $length Length to split. 240 * 241 * @return array A list containing individual sequence strings. 242 */ 243 public function split($length) 244 { 245 $id = new Horde_Stream_Temp(); 246 $id->add($this->tostring_sort, true); 247 248 $out = array(); 249 250 do { 251 $out[] = $id->substring(0, $length) . $id->getToChar(','); 252 } while (!$id->eof()); 253 254 return $out; 255 } 256 257 /** 258 * Resolve the $ids input to add() and remove(). 259 * 260 * @param mixed $ids Either Horde_Imap_Client_Ids object, array, or 261 * sequence string. 262 * 263 * @return array An array of IDs. 264 */ 265 protected function _resolveIds($ids) 266 { 267 if ($ids instanceof Horde_Imap_Client_Ids) { 268 return $ids->ids; 269 } elseif (is_array($ids)) { 270 return $ids; 271 } elseif (is_string($ids) || is_integer($ids)) { 272 return is_numeric($ids) 273 ? array($ids) 274 : $this->_fromSequenceString($ids); 275 } 276 277 return array(); 278 } 279 280 /** 281 * Create an IMAP message sequence string from a list of indices. 282 * 283 * Index Format: range_start:range_end,uid,uid2,... 284 * 285 * @param boolean $sort Numerically sort the IDs before creating the 286 * range? 287 * 288 * @return string The IMAP message sequence string. 289 */ 290 protected function _toSequenceString($sort = true) 291 { 292 if (empty($this->_ids)) { 293 return ''; 294 } 295 296 $in = $this->_ids; 297 298 if ($sort && !$this->_sorted) { 299 sort($in, SORT_NUMERIC); 300 } 301 302 $first = $last = array_shift($in); 303 $i = count($in) - 1; 304 $out = array(); 305 306 reset($in); 307 while (list($key, $val) = each($in)) { 308 if (($last + 1) == $val) { 309 $last = $val; 310 } 311 312 if (($i == $key) || ($last != $val)) { 313 if ($last == $first) { 314 $out[] = $first; 315 if ($i == $key) { 316 $out[] = $val; 317 } 318 } else { 319 $out[] = $first . ':' . $last; 320 if (($i == $key) && ($last != $val)) { 321 $out[] = $val; 322 } 323 } 324 $first = $last = $val; 325 } 326 } 327 328 return empty($out) 329 ? $first 330 : implode(',', $out); 331 } 332 333 /** 334 * Parse an IMAP message sequence string into a list of indices. 335 * 336 * @see _toSequenceString() 337 * 338 * @param string $str The IMAP message sequence string. 339 * 340 * @return array An array of indices. 341 */ 342 protected function _fromSequenceString($str) 343 { 344 $ids = array(); 345 $str = trim($str); 346 347 if (!strlen($str)) { 348 return $ids; 349 } 350 351 $idarray = explode(',', $str); 352 353 reset($idarray); 354 while (list(,$val) = each($idarray)) { 355 $range = explode(':', $val); 356 if (isset($range[1])) { 357 for ($i = min($range), $j = max($range); $i <= $j; ++$i) { 358 $ids[] = $i; 359 } 360 } else { 361 $ids[] = $val; 362 } 363 } 364 365 return $ids; 366 } 367 368 /* Countable methods. */ 369 370 /** 371 */ 372 public function count() 373 { 374 return is_array($this->_ids) 375 ? count($this->_ids) 376 : 0; 377 } 378 379 /* Iterator methods. */ 380 381 /** 382 */ 383 public function current() 384 { 385 return is_array($this->_ids) 386 ? current($this->_ids) 387 : null; 388 } 389 390 /** 391 */ 392 public function key() 393 { 394 return is_array($this->_ids) 395 ? key($this->_ids) 396 : null; 397 } 398 399 /** 400 */ 401 public function next() 402 { 403 if (is_array($this->_ids)) { 404 next($this->_ids); 405 } 406 } 407 408 /** 409 */ 410 public function rewind() 411 { 412 if (is_array($this->_ids)) { 413 reset($this->_ids); 414 } 415 } 416 417 /** 418 */ 419 public function valid() 420 { 421 return !is_null($this->key()); 422 } 423 424 /* Serializable methods. */ 425 426 /** 427 */ 428 public function serialize() 429 { 430 $save = array(); 431 432 if ($this->duplicates) { 433 $save['d'] = 1; 434 } 435 436 if ($this->_sequence) { 437 $save['s'] = 1; 438 } 439 440 if ($this->_sorted) { 441 $save['is'] = 1; 442 } 443 444 switch ($this->_ids) { 445 case self::ALL: 446 $save['a'] = true; 447 break; 448 449 case self::LARGEST: 450 $save['l'] = true; 451 break; 452 453 case self::SEARCH_RES: 454 $save['sr'] = true; 455 break; 456 457 default: 458 $save['i'] = strval($this); 459 break; 460 } 461 462 return serialize($save); 463 } 464 465 /** 466 */ 467 public function unserialize($data) 468 { 469 $save = @unserialize($data); 470 471 $this->duplicates = !empty($save['d']); 472 $this->_sequence = !empty($save['s']); 473 $this->_sorted = !empty($save['is']); 474 475 if (isset($save['a'])) { 476 $this->_ids = self::ALL; 477 } elseif (isset($save['l'])) { 478 $this->_ids = self::LARGEST; 479 } elseif (isset($save['sr'])) { 480 $this->_ids = self::SEARCH_RES; 481 } elseif (isset($save['i'])) { 482 $this->add($save['i']); 483 } 484 } 485 486 }
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 |