Thomas Bruederli
2012-10-03 7bcd291517e9aca620e8938e965347a73b620a7a
program/include/rcube_result_thread.php
@@ -7,7 +7,10 @@
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2005-2011, The Roundcube Dev Team                       |
 | Copyright (C) 2011, Kolab Systems AG                                  |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | Licensed under the GNU General Public License version 3 or            |
 | any later version with exceptions for skins & plugins.                |
 | See the README file for a full license statement.                     |
 |                                                                       |
 | PURPOSE:                                                              |
 |   THREAD response handler                                             |
@@ -16,9 +19,6 @@
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 | Author: Aleksander Machniak <alec@alec.pl>                            |
 +-----------------------------------------------------------------------+
 $Id: rcube_imap.php 5347 2011-10-19 06:35:29Z alec $
*/
@@ -27,10 +27,10 @@
 */
class rcube_result_thread
{
    private $raw_data;
    private $mailbox;
    private $meta = array();
    private $order = 'ASC';
    protected $raw_data;
    protected $mailbox;
    protected $meta = array();
    protected $order = 'ASC';
    const SEPARATOR_ELEMENT = ' ';
    const SEPARATOR_ITEM    = '~';
@@ -61,6 +61,8 @@
        // ...skip unilateral untagged server responses
        for ($i=0, $len=count($data); $i<$len; $i++) {
            if (preg_match('/^ THREAD/i', $data[$i])) {
                // valid response, initialize raw_data for is_error()
                $this->raw_data = '';
                $data[$i] = substr($data[$i], 7);
                break;
            }
@@ -77,7 +79,7 @@
        $data = preg_replace('/[\r\n]/', '', $data);
        $data = preg_replace('/\s+/', ' ', $data);
        $this->raw_data = $this->parseThread($data);
        $this->raw_data = $this->parse_thread($data);
    }
@@ -86,7 +88,7 @@
     *
     * @return bool True if the result is an error, False otherwise
     */
    public function isError()
    public function is_error()
    {
        return $this->raw_data === null ? true : false;
    }
@@ -97,7 +99,7 @@
     *
     * @return bool True if the result is empty, False otherwise
     */
    public function isEmpty()
    public function is_empty()
    {
        return empty($this->raw_data) ? true : false;
    }
@@ -132,7 +134,7 @@
     *
     * @return int Number of elements
     */
    public function countMessages()
    public function count_messages()
    {
        if ($this->meta['messages'] !== null)
            return $this->meta['messages'];
@@ -300,7 +302,7 @@
                    $idx = substr_count($this->raw_data, self::SEPARATOR_ELEMENT, 0, $m[0][1]+1)
                        + substr_count($this->raw_data, self::SEPARATOR_ITEM, 0, $m[0][1]+1);
                }
                // cache position of this element, so we can use it in getElement()
                // cache position of this element, so we can use it in get_element()
                $this->meta['pos'][$idx] = (int)$m[0][1];
                return $idx;
@@ -336,7 +338,7 @@
     *
     * @return array List of message identifiers
     */
    public function getCompressed()
    public function get_compressed()
    {
        if (empty($this->raw_data)) {
            return '';
@@ -353,7 +355,7 @@
     *
     * @return int Element value
     */
    public function getElement($index)
    public function get_element($index)
    {
        $count = $this->count();
@@ -423,7 +425,7 @@
     *
     * @return array|string Response parameters or parameter value
     */
    public function getParameters($param=null)
    public function get_parameters($param=null)
    {
        $params = $this->params;
        $params['MAILBOX'] = $this->mailbox;
@@ -444,14 +446,14 @@
     */
    public function sort($index)
    {
        $this->sort_order = $index->getParameters('ORDER');
        $this->sort_order = $index->get_parameters('ORDER');
        if (empty($this->raw_data)) {
            return;
        }
        // when sorting search result it's good to make the index smaller
        if ($index->count() != $this->countMessages()) {
        if ($index->count() != $this->count_messages()) {
            $index->intersect($this->get());
        }
@@ -510,7 +512,7 @@
     *
     * @return array Data tree
     */
    public function getTree()
    public function get_tree()
    {
        $datalen = strlen($this->raw_data);
        $result  = array();
@@ -522,7 +524,7 @@
            $len   = $pos - $start;
            $elem  = substr($this->raw_data, $start, $len);
            $items = explode(self::SEPARATOR_ITEM, $elem);
            $result[array_shift($items)] = $this->buildThread($items);
            $result[array_shift($items)] = $this->build_thread($items);
            $start = $pos + 1;
        }
@@ -535,13 +537,13 @@
     *
     * @return array Thread data
     */
    public function getThreadData()
    public function get_thread_data()
    {
        $data     = $this->getTree();
        $data     = $this->get_tree();
        $depth    = array();
        $children = array();
        $this->buildThreadData($data, $depth, $children);
        $this->build_thread_data($data, $depth, $children);
        return array($depth, $children);
    }
@@ -550,13 +552,15 @@
    /**
     * Creates 'depth' and 'children' arrays from stored thread 'tree' data.
     */
    private function buildThreadData($data, &$depth, &$children, $level = 0)
    protected function build_thread_data($data, &$depth, &$children, $level = 0)
    {
        foreach ((array)$data as $key => $val) {
            $children[$key] = !empty($val);
            $depth[$key] = $level;
            if (!empty($val))
                $this->buildThreadData($val, $depth, $children, $level + 1);
            $empty          = empty($val) || !is_array($val);
            $children[$key] = !$empty;
            $depth[$key]    = $level;
            if (!$empty) {
                $this->build_thread_data($val, $depth, $children, $level + 1);
            }
        }
    }
@@ -564,7 +568,7 @@
    /**
     * Converts part of the raw thread into an array
     */
    private function buildThread($items, $level = 1, &$pos = 0)
    protected function build_thread($items, $level = 1, &$pos = 0)
    {
        $result = array();
@@ -572,7 +576,7 @@
            list($lv, $id) = explode(self::SEPARATOR_LEVEL, $items[$pos]);
            if ($level == $lv) {
                $pos++;
                $result[$id] = $this->buildThread($items, $level+1, $pos);
                $result[$id] = $this->build_thread($items, $level+1, $pos);
            }
            else {
                $pos--;
@@ -587,7 +591,7 @@
    /**
     * IMAP THREAD response parser
     */
    private function parseThread($str, $begin = 0, $end = 0, $depth = 0)
    protected function parse_thread($str, $begin = 0, $end = 0, $depth = 0)
    {
        // Don't be tempted to change $str to pass by reference to speed this up - it will slow it down by about
        // 7 times instead :-) See comments on http://uk2.php.net/references and this article:
@@ -625,7 +629,7 @@
            $node .= ($depth ? self::SEPARATOR_ITEM.$depth.self::SEPARATOR_LEVEL : '').$msg;
            if ($stop + 1 < $end) {
                $node .= $this->parseThread($str, $stop + 1, $end, $depth + 1);
                $node .= $this->parse_thread($str, $stop + 1, $end, $depth + 1);
            }
        } else {
            $off = $begin;
@@ -650,7 +654,7 @@
                    }
                }
                $thread = $this->parseThread($str, $start + 1, $off - 1, $depth);
                $thread = $this->parse_thread($str, $start + 1, $off - 1, $depth);
                if ($thread) {
                    if (!$depth) {
                        if ($node) {