1: <?php
2: /**
3: * Object allowing easy access to threaded sort results from
4: * Horde_Imap_Client_Base::thread().
5: *
6: * Copyright 2008-2012 Horde LLC (http://www.horde.org/)
7: *
8: * See the enclosed file COPYING for license information (LGPL). If you
9: * did not receive this file, see http://www.horde.org/licenses/lgpl21.
10: *
11: * @author Michael Slusarz <slusarz@horde.org>
12: * @category Horde
13: * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
14: * @package Imap_Client
15: */
16: class Horde_Imap_Client_Data_Thread implements Countable, Serializable
17: {
18: /**
19: * Internal thread data structure.
20: *
21: * @var array
22: */
23: protected $_thread = array();
24:
25: /**
26: * The index type.
27: *
28: * @var string
29: */
30: protected $_type;
31:
32: /**
33: * Constructor.
34: *
35: * @param array $data The data as returned by
36: * Horde_Imap_Client_Base::_thread().
37: * @param string $type Either 'uid' or 'sequence'.
38: */
39: public function __construct($data, $type)
40: {
41: $this->_thread = $data;
42: $this->_type = $type;
43: }
44:
45: /**
46: * Return the raw thread data array.
47: *
48: * @return array See Horde_Imap_Client_Base::_thread().
49: */
50: public function getRawData()
51: {
52: return $this->_thread;
53: }
54:
55: /**
56: * Gets the indention level for an index.
57: *
58: * @param integer $index The index.
59: *
60: * @return mixed Returns the thread indent level if $index found.
61: * Returns false on failure.
62: */
63: public function getThreadIndent($index)
64: {
65: return isset($this->_thread[$index])
66: ? (isset($this->_thread[$index]['l']) ? $this->_thread[$index]['l'] : 0)
67: : false;
68: }
69:
70: /**
71: * Gets the base thread index for an index.
72: *
73: * @param integer $index The index.
74: *
75: * @return mixed Returns the base index if $index is part of a thread.
76: * Returns false on failure.
77: */
78: public function getThreadBase($index)
79: {
80: return isset($this->_thread[$index])
81: ? (isset($this->_thread[$index]['b']) ? $this->_thread[$index]['b'] : null)
82: : false;
83: }
84:
85: /**
86: * Is this index the last in the current level?
87: *
88: * @param integer $index The index.
89: *
90: * @return boolean Returns true if $index is the last element in the
91: * current thread level.
92: * Returns false if not, or on failure.
93: */
94: public function lastInLevel($index)
95: {
96: return empty($this->_thread[$index]['s']);
97: }
98:
99: /**
100: * Return the sorted list of messages indices.
101: *
102: * @return array The sorted list of messages.
103: */
104: public function messageList()
105: {
106: return array_keys($this->_thread);
107: }
108:
109: /**
110: * Returns the list of messages in the current thread.
111: *
112: * @param integer $index The index of the current message.
113: *
114: * @return array A list of message indices.
115: */
116: public function getThread($index)
117: {
118: /* Find the beginning of the thread. */
119: if (!($begin = $this->getThreadBase($index))) {
120: return array($index);
121: }
122:
123: /* Work forward from the first thread element to find the end of the
124: * thread. */
125: $in_thread = false;
126: $thread_list = array();
127: reset($this->_thread);
128: while (list($k, $v) = each($this->_thread)) {
129: if ($k == $begin) {
130: $in_thread = true;
131: } elseif ($in_thread && ($this->getThreadBase($k) != $begin)) {
132: break;
133: }
134:
135: if ($in_thread) {
136: $thread_list[] = $k;
137: }
138: }
139:
140: return $thread_list;
141: }
142:
143: /* Countable methods. */
144:
145: /**
146: */
147: public function count()
148: {
149: return count($this->_thread);
150: }
151:
152: /* Serializable methods. */
153:
154: /**
155: */
156: public function serialize()
157: {
158: return json_encode(array(
159: $this->_thread,
160: $this->_type
161: ));
162: }
163:
164: /**
165: */
166: public function unserialize($data)
167: {
168: list($this->_thread, $this->_type) = json_decode($data, true);
169: }
170:
171: }
172: