| | |
| | | <?php |
| | | |
| | | /* |
| | | /** |
| | | +-----------------------------------------------------------------------+ |
| | | | program/include/rcube_result_thread.php | |
| | | | | |
| | | | This file is part of the Roundcube Webmail client | |
| | | | Copyright (C) 2005-2011, The Roundcube Dev Team | |
| | | | Copyright (C) 2011, Kolab Systems AG | |
| | |
| | | | | |
| | | | PURPOSE: | |
| | | | THREAD response handler | |
| | | | | |
| | | +-----------------------------------------------------------------------+ |
| | | | Author: Thomas Bruederli <roundcube@gmail.com> | |
| | | | Author: Aleksander Machniak <alec@alec.pl> | |
| | | +-----------------------------------------------------------------------+ |
| | | */ |
| | | |
| | | |
| | | /** |
| | | * Class for accessing IMAP's THREAD result |
| | |
| | | */ |
| | | class rcube_result_thread |
| | | { |
| | | public $incomplete = false; |
| | | |
| | | protected $raw_data; |
| | | protected $mailbox; |
| | | protected $meta = array(); |
| | |
| | | $this->mailbox = $mailbox; |
| | | $this->init($data); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Initializes object with IMAP command response |
| | |
| | | $this->raw_data = $this->parse_thread($data); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Checks the result from IMAP command |
| | | * |
| | |
| | | return $this->raw_data === null ? true : false; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Checks if the result is empty |
| | | * |
| | |
| | | { |
| | | return empty($this->raw_data) ? true : false; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns number of elements (threads) in the result |
| | |
| | | |
| | | return $this->meta['count']; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns number of all messages in the result |
| | |
| | | return $this->meta['messages']; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns maximum message identifier in the result |
| | | * |
| | |
| | | return $this->meta['max']; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns minimum message identifier in the result |
| | | * |
| | |
| | | } |
| | | return $this->meta['min']; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Slices data set. |
| | |
| | | $this->meta['count'] = count($data); |
| | | $this->raw_data = implode(self::SEPARATOR_ELEMENT, $data); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Filters data set. Removes threads not listed in $roots list. |
| | |
| | | $this->raw_data = ltrim($result, self::SEPARATOR_ELEMENT); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Reverts order of elements in the result |
| | | */ |
| | |
| | | |
| | | $this->raw_data = rtrim($result, self::SEPARATOR_ELEMENT); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Check if the given message ID exists in the object |
| | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Return IDs of all messages in the result. Threaded data will be flattened. |
| | | * |
| | |
| | | return preg_split($regexp, $this->raw_data); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Return all messages in the result. |
| | | * |
| | |
| | | |
| | | return rcube_imap_generic::compressMessageSet($this->get()); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Return result element at specified index (all messages, not roots) |
| | |
| | | return $data[$index]; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns response parameters e.g. MAILBOX, ORDER |
| | | * |
| | | * @param string $param Parameter name |
| | | * @param string $param Parameter name |
| | | * |
| | | * @return array|string Response parameters or parameter value |
| | | */ |
| | | public function get_parameters($param=null) |
| | | { |
| | | $params = $this->params; |
| | | $params = array(); |
| | | $params['MAILBOX'] = $this->mailbox; |
| | | $params['ORDER'] = $this->order; |
| | | |
| | |
| | | |
| | | return $params; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * THREAD=REFS sorting implementation (based on provided index) |
| | |
| | | |
| | | // when sorting search result it's good to make the index smaller |
| | | if ($index->count() != $this->count_messages()) { |
| | | $index->intersect($this->get()); |
| | | $index->filter($this->get()); |
| | | } |
| | | |
| | | $result = array_fill_keys($index->get(), null); |
| | |
| | | $this->raw_data = implode(self::SEPARATOR_ELEMENT, $result); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns data as tree |
| | | * |
| | |
| | | return $result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns thread depth and children data |
| | | * |
| | |
| | | return array($depth, $children); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Creates 'depth' and 'children' arrays from stored thread 'tree' data. |
| | | */ |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Converts part of the raw thread into an array |
| | |
| | | return $result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * IMAP THREAD response parser |
| | | */ |
| | |
| | | // arrays handling is much more expensive |
| | | // For the following structure: THREAD (2)(3 6 (4 23)(44 7 96)) |
| | | // -- 2 |
| | | // |
| | | // -- 3 |
| | | // \-- 6 |
| | | // |-- 4 |
| | | // | \-- 23 |
| | | // | |
| | | // \-- 44 |
| | | // \-- 7 |
| | | // \-- 96 |
| | | // \-- 7 |
| | | // \-- 96 |
| | | // |
| | | // The output will be: 2,3^1:6^2:4^3:23^2:44^3:7^4:96 |
| | | |
| | | if ($str[$begin] != '(') { |
| | | $stop = $begin + strspn($str, '1234567890', $begin, $end - $begin); |
| | | $msg = substr($str, $begin, $stop - $begin); |
| | | if (!$msg) { |
| | | // find next bracket |
| | | $stop = $begin + strcspn($str, '()', $begin, $end - $begin); |
| | | $messages = explode(' ', trim(substr($str, $begin, $stop - $begin))); |
| | | |
| | | if (empty($messages)) { |
| | | return $node; |
| | | } |
| | | |
| | | $this->meta['messages']++; |
| | | |
| | | $node .= ($depth ? self::SEPARATOR_ITEM.$depth.self::SEPARATOR_LEVEL : '').$msg; |
| | | |
| | | if ($stop + 1 < $end) { |
| | | $node .= $this->parse_thread($str, $stop + 1, $end, $depth + 1); |
| | | foreach ($messages as $msg) { |
| | | if ($msg) { |
| | | $node .= ($depth ? self::SEPARATOR_ITEM.$depth.self::SEPARATOR_LEVEL : '').$msg; |
| | | $this->meta['messages']++; |
| | | $depth++; |
| | | } |
| | | } |
| | | } else { |
| | | |
| | | if ($stop < $end) { |
| | | $node .= $this->parse_thread($str, $stop, $end, $depth); |
| | | } |
| | | } |
| | | else { |
| | | $off = $begin; |
| | | while ($off < $end) { |
| | | $start = $off; |
| | |
| | | if ($p1 !== false && $p1 < $p) { |
| | | $off = $p1 + 1; |
| | | $n++; |
| | | } else { |
| | | } |
| | | else { |
| | | $off = $p + 1; |
| | | $n--; |
| | | } |