Aleksander Machniak
2014-08-24 5f58127eae9ed8c54c190506e11af13e8ba57170
commit | author | age
566747 1 <?php
T 2
3 /*
4  +-----------------------------------------------------------------------+
5  | This file is part of the Roundcube Webmail client                     |
6  | Copyright (C) 2005-2011, The Roundcube Dev Team                       |
7  | Copyright (C) 2011, Kolab Systems AG                                  |
8  |                                                                       |
9  | Licensed under the GNU General Public License version 3 or            |
10  | any later version with exceptions for skins & plugins.                |
11  | See the README file for a full license statement.                     |
12  |                                                                       |
13  | PURPOSE:                                                              |
14  |   SORT/SEARCH/ESEARCH response handler                                |
15  +-----------------------------------------------------------------------+
16  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
17  +-----------------------------------------------------------------------+
18 */
19
20 /**
21  * Class holding a set of rcube_result_index instances that together form a
22  * result set of a multi-folder search
23  *
24  * @package    Framework
25  * @subpackage Storage
26  */
27 class rcube_result_multifolder
28 {
47a783 29     public $multi      = true;
AM 30     public $sets       = array();
31aa08 31     public $incomplete = false;
2c33c7 32     public $folder;
566747 33
47a783 34     protected $meta    = array();
AM 35     protected $index   = array();
e8cb51 36     protected $folders = array();
47a783 37     protected $order   = 'ASC';
2c33c7 38     protected $sorting;
566747 39
T 40
41     /**
42      * Object constructor.
43      */
e8cb51 44     public function __construct($folders = array())
566747 45     {
e8cb51 46         $this->folders = $folders;
47a783 47         $this->meta    = array('count' => 0);
566747 48     }
T 49
50
51     /**
52      * Initializes object with SORT command response
53      *
54      * @param string $data IMAP response string
55      */
56     public function add($result)
57     {
31aa08 58         $this->sets[] = $result;
TB 59
6f9bb1 60         if ($result->count()) {
TB 61             $this->append_result($result);
31aa08 62         }
TB 63         else if ($result->incomplete) {
64             $this->incomplete = true;
689a22 65         }
6f9bb1 66     }
TB 67
68     /**
69      * Append message UIDs from the given result to our index
70      */
71     protected function append_result($result)
72     {
73         $this->meta['count'] += $result->count();
74
75         // append UIDs to global index
76         $folder = $result->get_parameters('MAILBOX');
47a783 77         $index  = array_map(function($uid) use ($folder) { return $uid . '-' . $folder; }, $result->get());
AM 78
6f9bb1 79         $this->index = array_merge($this->index, $index);
566747 80     }
T 81
2c33c7 82     /**
TB 83      * Store a global index of (sorted) message UIDs
84      */
85     public function set_message_index($headers, $sort_field, $sort_order)
86     {
87         $this->index = array();
88         foreach ($headers as $header) {
89             $this->index[] = $header->uid . '-' . $header->folder;
90         }
91
92         $this->sorting = $sort_field;
47a783 93         $this->order   = $sort_order;
2c33c7 94     }
566747 95
T 96     /**
97      * Checks the result from IMAP command
98      *
99      * @return bool True if the result is an error, False otherwise
100      */
101     public function is_error()
102     {
103         return false;
104     }
105
106
107     /**
108      * Checks if the result is empty
109      *
110      * @return bool True if the result is empty, False otherwise
111      */
112     public function is_empty()
113     {
114         return empty($this->sets) || $this->meta['count'] == 0;
115     }
116
117
118     /**
119      * Returns number of elements in the result
120      *
121      * @return int Number of elements
122      */
123     public function count()
124     {
125         return $this->meta['count'];
126     }
127
128
129     /**
130      * Returns number of elements in the result.
131      * Alias for count() for compatibility with rcube_result_thread
132      *
133      * @return int Number of elements
134      */
135     public function count_messages()
136     {
137         return $this->count();
138     }
139
140
141     /**
142      * Reverts order of elements in the result
143      */
144     public function revert()
145     {
146         $this->order = $this->order == 'ASC' ? 'DESC' : 'ASC';
94e797 147         $this->index = array();
TB 148
149         // revert order in all sub-sets
150         foreach ($this->sets as $set) {
151             if ($this->order != $set->get_parameters('ORDER')) {
152                 $set->revert();
153             }
47a783 154
94e797 155             $folder = $set->get_parameters('MAILBOX');
47a783 156             $index  = array_map(function($uid) use ($folder) { return $uid . '-' . $folder; }, $set->get());
AM 157
94e797 158             $this->index = array_merge($this->index, $index);
TB 159         }
566747 160     }
T 161
162
163     /**
164      * Check if the given message ID exists in the object
165      *
166      * @param int  $msgid     Message ID
167      * @param bool $get_index When enabled element's index will be returned.
168      *                        Elements are indexed starting with 0
169      * @return mixed False if message ID doesn't exist, True if exists or
170      *               index of the element if $get_index=true
171      */
172     public function exists($msgid, $get_index = false)
173     {
2c33c7 174         if (!empty($this->folder)) {
TB 175             $msgid .= '-' . $this->folder;
176         }
47a783 177
2c33c7 178         return array_search($msgid, $this->index);
566747 179     }
T 180
181
182     /**
183      * Filters data set. Removes elements listed in $ids list.
184      *
185      * @param array $ids List of IDs to remove.
186      * @param string $folder IMAP folder
187      */
188     public function filter($ids = array(), $folder = null)
189     {
190         $this->meta['count'] = 0;
191         foreach ($this->sets as $set) {
192             if ($set->get_parameters('MAILBOX') == $folder) {
193                 $set->filter($ids);
194             }
47a783 195
566747 196             $this->meta['count'] += $set->count();
T 197         }
198     }
199
200     /**
188304 201      * Slices data set.
TB 202      *
203      * @param $offset Offset (as for PHP's array_slice())
204      * @param $length Number of elements (as for PHP's array_slice())
205      *
206      */
207     public function slice($offset, $length)
208     {
209         $data = array_slice($this->get(), $offset, $length);
210
211         $this->index = $data;
212         $this->meta['count'] = count($data);
213     }
214
215     /**
566747 216      * Filters data set. Removes elements not listed in $ids list.
T 217      *
218      * @param array $ids List of IDs to keep.
219      */
220     public function intersect($ids = array())
221     {
222         // not implemented
223     }
224
225     /**
226      * Return all messages in the result.
227      *
228      * @return array List of message IDs
229      */
230     public function get()
231     {
2c33c7 232         return $this->index;
566747 233     }
T 234
235
236     /**
237      * Return all messages in the result.
238      *
239      * @return array List of message IDs
240      */
241     public function get_compressed()
242     {
243         return '';
244     }
245
246
247     /**
248      * Return result element at specified index
249      *
250      * @param int|string  $index  Element's index or "FIRST" or "LAST"
251      *
252      * @return int Element value
253      */
2c33c7 254     public function get_element($idx)
566747 255     {
2c33c7 256         switch ($idx) {
TB 257             case 'FIRST': return $this->index[0];
258             case 'LAST':  return end($this->index);
259             default:      return $this->index[$idx];
260         }
566747 261     }
T 262
263
264     /**
265      * Returns response parameters, e.g. ESEARCH's MIN/MAX/COUNT/ALL/MODSEQ
266      * or internal data e.g. MAILBOX, ORDER
267      *
268      * @param string $param  Parameter name
269      *
270      * @return array|string Response parameters or parameter value
271      */
272     public function get_parameters($param=null)
273     {
2c33c7 274         $params = array(
47a783 275             'SORT'    => $this->sorting,
AM 276             'ORDER'   => $this->order,
e8cb51 277             'MAILBOX' => $this->folders,
2c33c7 278         );
TB 279
280         if ($param !== null) {
281             return $params[$param];
282         }
283
566747 284         return $params;
T 285     }
286
31aa08 287     /**
TB 288      * Returns the stored result object for a particular folder
289      *
290      * @param string $folder  Folder name
291      * @return false|obejct rcube_result_* instance of false if none found
292      */
293     public function get_set($folder)
294     {
295         foreach ($this->sets as $set) {
296             if ($set->get_parameters('MAILBOX') == $folder) {
297                 return $set;
298             }
299         }
300
301         return false;
302     }
566747 303
T 304     /**
305      * Returns length of internal data representation
306      *
307      * @return int Data length
308      */
309     protected function length()
310     {
311         return $this->count();
312     }
31aa08 313
TB 314
315     /* Serialize magic methods */
316
317     public function __sleep()
318     {
319         return array('sets','folders','sorting','order');
320     }
321
322     public function __wakeup()
323     {
324         // restore index from saved result sets
325         $this->meta = array('count' => 0);
326
327         foreach ($this->sets as $result) {
6f9bb1 328             if ($result->count()) {
TB 329                 $this->append_result($result);
31aa08 330             }
TB 331             else if ($result->incomplete) {
332                 $this->incomplete = true;
333             }
334         }
335     }
336
566747 337 }