LDAPAccountManager/lam/lib/3rdParty/composer/pear-pear.horde.org/Horde_Imap_Client/Horde/Imap/Client/Ids.php

495 lines
12 KiB
PHP

<?php
/**
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
*
* @category Horde
* @copyright 2011-2017 Horde LLC
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Imap_Client
*/
/**
* An object that provides a way to identify a list of IMAP indices.
*
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 2011-2017 Horde LLC
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Imap_Client
*
* @property-read boolean $all Does this represent an ALL message set?
* @property-read array $ids The list of IDs.
* @property-read boolean $largest Does this represent the largest ID in use?
* @property-read string $max The largest ID (@since 2.20.0).
* @property-read string $min The smallest ID (@since 2.20.0).
* @property-read string $range_string Generates a range string consisting of
* all messages between begin and end of
* ID list.
* @property-read boolean $search_res Does this represent a search result?
* @property-read boolean $sequence Are these sequence IDs? If false, these
* are UIDs.
* @property-read boolean $special True if this is a "special" ID
* representation.
* @property-read string $tostring Return the non-sorted string
* representation.
* @property-read string $tostring_sort Return the sorted string
* representation.
*/
class Horde_Imap_Client_Ids implements Countable, Iterator, Serializable
{
/**
* "Special" representation constants.
*/
const ALL = "\01";
const SEARCH_RES = "\02";
const LARGEST = "\03";
/**
* Allow duplicate IDs?
*
* @var boolean
*/
public $duplicates = false;
/**
* List of IDs.
*
* @var mixed
*/
protected $_ids = array();
/**
* Are IDs message sequence numbers?
*
* @var boolean
*/
protected $_sequence = false;
/**
* Are IDs sorted?
*
* @var boolean
*/
protected $_sorted = false;
/**
* Constructor.
*
* @param mixed $ids See self::add().
* @param boolean $sequence Are $ids message sequence numbers?
*/
public function __construct($ids = null, $sequence = false)
{
$this->add($ids);
$this->_sequence = $sequence;
}
/**
*/
public function __get($name)
{
switch ($name) {
case 'all':
return ($this->_ids === self::ALL);
case 'ids':
return is_array($this->_ids)
? $this->_ids
: array();
case 'largest':
return ($this->_ids === self::LARGEST);
case 'max':
$this->sort();
return end($this->_ids);
case 'min':
$this->sort();
return reset($this->_ids);
case 'range_string':
if (!count($this)) {
return '';
}
$min = $this->min;
$max = $this->max;
return ($min == $max)
? $min
: $min . ':' . $max;
case 'search_res':
return ($this->_ids === self::SEARCH_RES);
case 'sequence':
return (bool)$this->_sequence;
case 'special':
return is_string($this->_ids);
case 'tostring':
case 'tostring_sort':
if ($this->all) {
return '1:*';
} elseif ($this->largest) {
return '*';
} elseif ($this->search_res) {
return '$';
}
return strval($this->_toSequenceString($name == 'tostring_sort'));
}
}
/**
*/
public function __toString()
{
return $this->tostring;
}
/**
* Add IDs to the current object.
*
* @param mixed $ids Either self::ALL, self::SEARCH_RES, self::LARGEST,
* Horde_Imap_Client_Ids object, array, or sequence
* string.
*/
public function add($ids)
{
if (!is_null($ids)) {
if (is_string($ids) &&
in_array($ids, array(self::ALL, self::SEARCH_RES, self::LARGEST))) {
$this->_ids = $ids;
} elseif ($add = $this->_resolveIds($ids)) {
if (is_array($this->_ids) && !empty($this->_ids)) {
foreach ($add as $val) {
$this->_ids[] = $val;
}
} else {
$this->_ids = $add;
}
if (!$this->duplicates) {
$this->_ids = (count($this->_ids) > 25000)
? array_unique($this->_ids)
: array_keys(array_flip($this->_ids));
}
}
$this->_sorted = is_array($this->_ids) && (count($this->_ids) === 1);
}
}
/**
* Removed IDs from the current object.
*
* @since 2.17.0
*
* @param mixed $ids Either Horde_Imap_Client_Ids object, array, or
* sequence string.
*/
public function remove($ids)
{
if (!$this->isEmpty() &&
($remove = $this->_resolveIds($ids))) {
$this->_ids = array_diff($this->_ids, array_unique($remove));
}
}
/**
* Is this object empty (i.e. does not contain IDs)?
*
* @return boolean True if object is empty.
*/
public function isEmpty()
{
return (is_array($this->_ids) && !count($this->_ids));
}
/**
* Reverses the order of the IDs.
*/
public function reverse()
{
if (is_array($this->_ids)) {
$this->_ids = array_reverse($this->_ids);
}
}
/**
* Sorts the IDs.
*/
public function sort()
{
if (!$this->_sorted && is_array($this->_ids)) {
$this->_sort($this->_ids);
$this->_sorted = true;
}
}
/**
* Sorts the IDs numerically.
*
* @param array $ids The array list.
*/
protected function _sort(&$ids)
{
sort($ids, SORT_NUMERIC);
}
/**
* Split the sequence string at an approximate length.
*
* @since 2.7.0
*
* @param integer $length Length to split.
*
* @return array A list containing individual sequence strings.
*/
public function split($length)
{
$id = new Horde_Stream_Temp();
$id->add($this->tostring_sort, true);
$out = array();
do {
$out[] = $id->substring(0, $length) . $id->getToChar(',');
} while (!$id->eof());
return $out;
}
/**
* Resolve the $ids input to add() and remove().
*
* @param mixed $ids Either Horde_Imap_Client_Ids object, array, or
* sequence string.
*
* @return array An array of IDs.
*/
protected function _resolveIds($ids)
{
if ($ids instanceof Horde_Imap_Client_Ids) {
return $ids->ids;
} elseif (is_array($ids)) {
return $ids;
} elseif (is_string($ids) || is_integer($ids)) {
return is_numeric($ids)
? array($ids)
: $this->_fromSequenceString($ids);
}
return array();
}
/**
* Create an IMAP message sequence string from a list of indices.
*
* Index Format: range_start:range_end,uid,uid2,...
*
* @param boolean $sort Numerically sort the IDs before creating the
* range?
*
* @return string The IMAP message sequence string.
*/
protected function _toSequenceString($sort = true)
{
if (empty($this->_ids)) {
return '';
}
$in = $this->_ids;
if ($sort && !$this->_sorted) {
$this->_sort($in);
}
$first = $last = array_shift($in);
$i = count($in) - 1;
$out = array();
foreach ($in as $key => $val) {
if (($last + 1) == $val) {
$last = $val;
}
if (($i == $key) || ($last != $val)) {
if ($last == $first) {
$out[] = $first;
if ($i == $key) {
$out[] = $val;
}
} else {
$out[] = $first . ':' . $last;
if (($i == $key) && ($last != $val)) {
$out[] = $val;
}
}
$first = $last = $val;
}
}
return empty($out)
? $first
: implode(',', $out);
}
/**
* Parse an IMAP message sequence string into a list of indices.
*
* @see _toSequenceString()
*
* @param string $str The IMAP message sequence string.
*
* @return array An array of indices.
*/
protected function _fromSequenceString($str)
{
$ids = array();
$str = trim($str);
if (!strlen($str)) {
return $ids;
}
$idarray = explode(',', $str);
foreach ($idarray as $val) {
$range = explode(':', $val);
if (isset($range[1])) {
for ($i = min($range), $j = max($range); $i <= $j; ++$i) {
$ids[] = $i;
}
} else {
$ids[] = $val;
}
}
return $ids;
}
/* Countable methods. */
/**
*/
public function count()
{
return is_array($this->_ids)
? count($this->_ids)
: 0;
}
/* Iterator methods. */
/**
*/
public function current()
{
return is_array($this->_ids)
? current($this->_ids)
: null;
}
/**
*/
public function key()
{
return is_array($this->_ids)
? key($this->_ids)
: null;
}
/**
*/
public function next()
{
if (is_array($this->_ids)) {
next($this->_ids);
}
}
/**
*/
public function rewind()
{
if (is_array($this->_ids)) {
reset($this->_ids);
}
}
/**
*/
public function valid()
{
return !is_null($this->key());
}
/* Serializable methods. */
/**
*/
public function serialize()
{
$save = array();
if ($this->duplicates) {
$save['d'] = 1;
}
if ($this->_sequence) {
$save['s'] = 1;
}
if ($this->_sorted) {
$save['is'] = 1;
}
switch ($this->_ids) {
case self::ALL:
$save['a'] = true;
break;
case self::LARGEST:
$save['l'] = true;
break;
case self::SEARCH_RES:
$save['sr'] = true;
break;
default:
$save['i'] = strval($this);
break;
}
return serialize($save);
}
/**
*/
public function unserialize($data)
{
$save = @unserialize($data);
$this->duplicates = !empty($save['d']);
$this->_sequence = !empty($save['s']);
$this->_sorted = !empty($save['is']);
if (isset($save['a'])) {
$this->_ids = self::ALL;
} elseif (isset($save['l'])) {
$this->_ids = self::LARGEST;
} elseif (isset($save['sr'])) {
$this->_ids = self::SEARCH_RES;
} elseif (isset($save['i'])) {
$this->add($save['i']);
}
}
}