Overview

Packages

  • IMP
  • None

Classes

  • IMP
  • IMP_Ajax_Application
  • IMP_Ajax_Imple_ContactAutoCompleter
  • IMP_Ajax_Imple_PassphraseDialog
  • IMP_Ajax_Queue
  • IMP_Api
  • IMP_Auth
  • IMP_Block_Newmail
  • IMP_Block_Summary
  • IMP_Compose
  • IMP_Compose_Exception
  • IMP_Compose_Stationery
  • IMP_Contents
  • IMP_Crypt_Pgp
  • IMP_Crypt_Smime
  • IMP_Dimp
  • IMP_Exception
  • IMP_Factory_AuthImap
  • IMP_Factory_Compose
  • IMP_Factory_Contents
  • IMP_Factory_Flags
  • IMP_Factory_Identity
  • IMP_Factory_Imap
  • IMP_Factory_Imaptree
  • IMP_Factory_Mail
  • IMP_Factory_Mailbox
  • IMP_Factory_MailboxList
  • IMP_Factory_MimeViewer
  • IMP_Factory_Pgp
  • IMP_Factory_Quota
  • IMP_Factory_Search
  • IMP_Factory_Sentmail
  • IMP_Factory_Smime
  • IMP_Filter
  • IMP_Flag_Base
  • IMP_Flag_Imap
  • IMP_Flag_Imap_Answered
  • IMP_Flag_Imap_Deleted
  • IMP_Flag_Imap_Draft
  • IMP_Flag_Imap_Flagged
  • IMP_Flag_Imap_Forwarded
  • IMP_Flag_Imap_Junk
  • IMP_Flag_Imap_NotJunk
  • IMP_Flag_Imap_Seen
  • IMP_Flag_System_Attachment
  • IMP_Flag_System_Encrypted
  • IMP_Flag_System_HighPriority
  • IMP_Flag_System_List
  • IMP_Flag_System_LowPriority
  • IMP_Flag_System_Match_Address
  • IMP_Flag_System_Match_Flag
  • IMP_Flag_System_Match_Header
  • IMP_Flag_System_Personal
  • IMP_Flag_System_Signed
  • IMP_Flag_System_Unseen
  • IMP_Flag_User
  • IMP_Flags
  • IMP_Imap
  • IMP_Imap_Acl
  • IMP_Imap_Exception
  • IMP_Imap_PermanentFlags
  • IMP_Imap_Thread
  • IMP_Imap_Tree
  • IMP_Indices
  • IMP_Indices_Form
  • IMP_LoginTasks_SystemTask_GarbageCollection
  • IMP_LoginTasks_SystemTask_Upgrade
  • IMP_LoginTasks_SystemTask_UpgradeAuth
  • IMP_LoginTasks_Task_Autocreate
  • IMP_LoginTasks_Task_DeleteAttachmentsMonthly
  • IMP_LoginTasks_Task_DeleteSentmailMonthly
  • IMP_LoginTasks_Task_FilterOnLogin
  • IMP_LoginTasks_Task_PurgeSentmail
  • IMP_LoginTasks_Task_PurgeSpam
  • IMP_LoginTasks_Task_PurgeTrash
  • IMP_LoginTasks_Task_RecoverDraft
  • IMP_LoginTasks_Task_RenameSentmailMonthly
  • IMP_Mailbox
  • IMP_Mailbox_List
  • IMP_Mailbox_List_Track
  • IMP_Maillog
  • IMP_Menu_Dimp
  • IMP_Message
  • IMP_Mime_Status
  • IMP_Mime_Viewer_Alternative
  • IMP_Mime_Viewer_Appledouble
  • IMP_Mime_Viewer_Audio
  • IMP_Mime_Viewer_Enriched
  • IMP_Mime_Viewer_Externalbody
  • IMP_Mime_Viewer_Html
  • IMP_Mime_Viewer_Images
  • IMP_Mime_Viewer_Itip
  • IMP_Mime_Viewer_Mdn
  • IMP_Mime_Viewer_Partial
  • IMP_Mime_Viewer_Pdf
  • IMP_Mime_Viewer_Pgp
  • IMP_Mime_Viewer_Plain
  • IMP_Mime_Viewer_Related
  • IMP_Mime_Viewer_Rfc822
  • IMP_Mime_Viewer_Smil
  • IMP_Mime_Viewer_Smime
  • IMP_Mime_Viewer_Status
  • IMP_Mime_Viewer_Vcard
  • IMP_Mime_Viewer_Video
  • IMP_Mime_Viewer_Zip
  • IMP_Notification_Event_Status
  • IMP_Notification_Handler_Decorator_ImapAlerts
  • IMP_Notification_Handler_Decorator_NewmailNotify
  • IMP_Notification_Listener_AjaxStatus
  • Imp_Prefs_Identity
  • IMP_Prefs_Ui
  • IMP_Quota
  • IMP_Quota_Base
  • IMP_Quota_Command
  • IMP_Quota_Hook
  • IMP_Quota_Imap
  • IMP_Quota_Maildir
  • IMP_Quota_Mdaemon
  • IMP_Quota_Mercury32
  • IMP_Quota_Null
  • IMP_Quota_Sql
  • IMP_Search
  • IMP_Search_Element
  • IMP_Search_Element_Attachment
  • IMP_Search_Element_Autogenerated
  • IMP_Search_Element_Bulk
  • IMP_Search_Element_Contacts
  • IMP_Search_Element_Date
  • IMP_Search_Element_Flag
  • IMP_Search_Element_Header
  • IMP_Search_Element_Mailinglist
  • IMP_Search_Element_Or
  • IMP_Search_Element_Personal
  • IMP_Search_Element_Recipient
  • IMP_Search_Element_Size
  • IMP_Search_Element_Text
  • IMP_Search_Element_Within
  • IMP_Search_Filter
  • IMP_Search_Filter_Attachment
  • IMP_Search_Filter_Autogenerated
  • IMP_Search_Filter_Builtin
  • IMP_Search_Filter_Bulk
  • IMP_Search_Filter_Contacts
  • IMP_Search_Filter_Mailinglist
  • IMP_Search_Filter_Personal
  • IMP_Search_Query
  • IMP_Search_Vfolder
  • IMP_Search_Vfolder_Builtin
  • IMP_Search_Vfolder_Vinbox
  • IMP_Search_Vfolder_Vtrash
  • IMP_Sentmail
  • IMP_Sentmail_Base
  • IMP_Sentmail_Null
  • IMP_Sentmail_Sql
  • IMP_Spam
  • IMP_Test
  • IMP_Tree_Flist
  • IMP_Tree_Jquerymobile
  • IMP_Tree_Simplehtml
  • IMP_Ui_Compose
  • IMP_Ui_Editor
  • IMP_Ui_Folder
  • IMP_Ui_Headers
  • IMP_Ui_Imageview
  • IMP_Ui_Mailbox
  • IMP_Ui_Message
  • IMP_Ui_Mimp
  • IMP_Ui_Search
  • IMP_Views_Compose
  • IMP_Views_ListMessages
  • IMP_Views_ShowMessage
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * This class contains code related to generating and handling a mailbox
  4:  * message list.
  5:  *
  6:  * Copyright 2002-2012 Horde LLC (http://www.horde.org/)
  7:  *
  8:  * See the enclosed file COPYING for license information (GPL). If you
  9:  * did not receive this file, see http://www.horde.org/licenses/gpl.
 10:  *
 11:  * @author   Michael Slusarz <slusarz@horde.org>
 12:  * @category Horde
 13:  * @license  http://www.horde.org/licenses/gpl GPL
 14:  * @package  IMP
 15:  */
 16: class IMP_Mailbox_List implements ArrayAccess, Countable, Iterator, Serializable
 17: {
 18:     /* Serialized version. */
 19:     const VERSION = 2;
 20: 
 21:     /**
 22:      * Has the internal message list changed?
 23:      *
 24:      * @var boolean
 25:      */
 26:     public $changed = false;
 27: 
 28:     /**
 29:      * The mailbox to work with.
 30:      *
 31:      * @var IMP_Mailbox
 32:      */
 33:     protected $_mailbox;
 34: 
 35:     /**
 36:      * The list of additional variables to serialize.
 37:      *
 38:      * @var array
 39:      */
 40:     protected $_slist = array();
 41: 
 42:     /**
 43:      * The array of sorted indices.
 44:      *
 45:      * @var array
 46:      */
 47:     protected $_sorted = null;
 48: 
 49:     /**
 50:      * The mailboxes corresponding to the sorted indices list.
 51:      * If empty, uses $_mailbox.
 52:      *
 53:      * @var array
 54:      */
 55:     protected $_sortedMbox = array();
 56: 
 57:     /**
 58:      * The thread object for the mailbox.
 59:      *
 60:      * @var Horde_Imap_Client_Data_Thread
 61:      */
 62:     protected $_threadob = null;
 63: 
 64:     /**
 65:      * Constructor.
 66:      *
 67:      * @param string $mbox  The mailbox to work with.
 68:      */
 69:     public function __construct($mbox)
 70:     {
 71:         $this->_mailbox = IMP_Mailbox::get($mbox);
 72:     }
 73: 
 74:     /**
 75:      * Build the array of message information.
 76:      *
 77:      * @param array $msgnum   An array of message sequence numbers.
 78:      * @param array $options  Additional options:
 79:      * <pre>
 80:      * headers - (boolean) Return info on the non-envelope headers
 81:      *           'Importance', 'List-Post', and 'X-Priority'.
 82:      *           DEFAULT: false (only envelope headers returned)
 83:      * preview - (mixed) Include preview information?  If empty, add no
 84:      *                   preview information. If 1, uses value from prefs.
 85:      *                   If 2, forces addition of preview info.
 86:      *                   DEFAULT: No preview information.
 87:      * type - (boolean) Return info on the MIME Content-Type of the base
 88:      *        message part ('Content-Type' header).
 89:      *        DEFAULT: false
 90:      * </pre>
 91:      *
 92:      * @return array  An array with the following keys:
 93:      * <pre>
 94:      * overview - (array) The overview information. Contains the following:
 95:      *     envelope - (Horde_Imap_Client_Data_Envelope) Envelope information
 96:      *                returned from the IMAP server.
 97:      *     flags - (array) The list of IMAP flags returned from the server.
 98:      *     headers - (array) Horde_Mime_Headers objects containing header data
 99:      *               if either $options['headers'] or $options['type'] are
100:      *               true.
101:      *     mailbox - (string) The mailbox containing the message.
102:      *     preview - (string) If requested in $options['preview'], the preview
103:      *               text.
104:      *     previewcut - (boolean) Has the preview text been cut?
105:      *     size - (integer) The size of the message in bytes.
106:      *     uid - (string) The unique ID of the message.
107:      * uids - (IMP_Indices) An indices object.
108:      * </pre>
109:      */
110:     public function getMailboxArray($msgnum, $options = array())
111:     {
112:         $this->_buildMailbox();
113: 
114:         $headers = $overview = $to_process = $uids = array();
115: 
116:         /* Build the list of mailboxes and messages. */
117:         foreach ($msgnum as $i) {
118:             /* Make sure that the index is actually in the slice of messages
119:                we're looking at. If we're hiding deleted messages, for
120:                example, there may be gaps here. */
121:             if (isset($this->_sorted[$i - 1])) {
122:                 $mboxname = $this->_mailbox->search
123:                     ? $this->_sortedMbox[$i - 1]
124:                     : strval($this->_mailbox);
125: 
126:                 // $uids - KEY: UID, VALUE: sequence number
127:                 $to_process[$mboxname][$this->_sorted[$i - 1]] = $i;
128:             }
129:         }
130: 
131:         $fetch_query = new Horde_Imap_Client_Fetch_Query();
132:         $fetch_query->envelope();
133:         $fetch_query->flags();
134:         $fetch_query->size();
135:         $fetch_query->uid();
136: 
137:         if (!empty($options['headers'])) {
138:             $headers = array_merge($headers, array(
139:                 'importance',
140:                 'list-post',
141:                 'x-priority'
142:             ));
143:         }
144: 
145:         if (!empty($options['type'])) {
146:             $headers[] = 'content-type';
147:         }
148: 
149:         if (!empty($headers)) {
150:             $fetch_query->headers('imp', $headers, array(
151:                 'cache' => true,
152:                 'peek' => true
153:             ));
154:         }
155: 
156:         $imp_imap = $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create();
157: 
158:         if (empty($options['preview'])) {
159:             $cache = null;
160:             $options['preview'] = 0;
161:         } else {
162:             $cache = $imp_imap->getCache();
163:         }
164: 
165:         /* Retrieve information from each mailbox. */
166:         foreach ($to_process as $mbox => $ids) {
167:             try {
168:                 $fetch_res = $imp_imap->fetch($mbox, $fetch_query, array(
169:                     'ids' => $imp_imap->getIdsOb(array_keys($ids))
170:                 ));
171: 
172:                 if ($options['preview']) {
173:                     $preview_info = $tostore = array();
174:                     if ($cache) {
175:                         try {
176:                             $preview_info = $cache->get($mbox, array_keys($ids), array('IMPpreview', 'IMPpreviewc'));
177:                         } catch (IMP_Imap_Exception $e) {}
178:                     }
179:                 }
180: 
181:                 reset($fetch_res);
182:                 while (list($k, $f) = each($fetch_res)) {
183:                     $v = array(
184:                         'envelope' => $f->getEnvelope(),
185:                         'flags' => $f->getFlags(),
186:                         'headers' => $f->getHeaders('imp', Horde_Imap_Client_Data_Fetch::HEADER_PARSE),
187:                         'mailbox' => $mbox,
188:                         'size' => $f->getSize(),
189:                         'uid' => $f->getUid()
190:                     );
191: 
192:                     if (($options['preview'] === 2) ||
193:                         (($options['preview'] === 1) &&
194:                          (!$GLOBALS['prefs']->getValue('preview_show_unread') ||
195:                           !in_array(Horde_Imap_Client::FLAG_SEEN, $v['flags'])))) {
196:                         if (empty($preview_info[$k])) {
197:                             try {
198:                                 $imp_contents = $GLOBALS['injector']->getInstance('IMP_Factory_Contents')->create(new IMP_Indices($mbox, $k));
199:                                 $prev = $imp_contents->generatePreview();
200:                                 $preview_info[$k] = array('IMPpreview' => $prev['text'], 'IMPpreviewc' => $prev['cut']);
201:                                 if (!is_null($cache)) {
202:                                     $tostore[$k] = $preview_info[$k];
203:                                 }
204:                             } catch (Exception $e) {
205:                                 $preview_info[$k] = array('IMPpreview' => '', 'IMPpreviewc' => false);
206:                             }
207:                         }
208: 
209:                         $v['preview'] = $preview_info[$k]['IMPpreview'];
210:                         $v['previewcut'] = $preview_info[$k]['IMPpreviewc'];
211:                     }
212: 
213:                     $overview[] = $v;
214:                 }
215: 
216:                 $uids[$mbox] = array_keys($fetch_res);
217: 
218:                 if (!is_null($cache) && !empty($tostore)) {
219:                     $status = $imp_imap->status($mbox, Horde_Imap_Client::STATUS_UIDVALIDITY);
220:                     $cache->set($mbox, $tostore, $status['uidvalidity']);
221:                 }
222:             } catch (IMP_Imap_Exception $e) {}
223:         }
224: 
225:         return array(
226:             'overview' => $overview,
227:             'uids' => new IMP_Indices($uids)
228:         );
229:     }
230: 
231:     /**
232:      * Returns true if the mailbox data has been built.
233:      *
234:      * @return boolean  True if the mailbox has been built.
235:      */
236:     public function isBuilt()
237:     {
238:         return !is_null($this->_sorted);
239:     }
240: 
241:     /**
242:      * Builds the sorted list of messages in the mailbox.
243:      */
244:     protected function _buildMailbox()
245:     {
246:         if ($this->isBuilt()) {
247:             return;
248:         }
249: 
250:         $this->changed = true;
251:         $this->_sorted = $this->_sortedMbox = array();
252:         $query = null;
253: 
254:         if ($this->_mailbox->search) {
255:             if ($this->_mailbox->hideDeletedMsgs()) {
256:                 $query = new Horde_Imap_Client_Search_Query();
257:                 $query->flag(Horde_Imap_Client::FLAG_DELETED, false);
258:             }
259: 
260:             try {
261:                 foreach ($GLOBALS['injector']->getInstance('IMP_Search')->runSearch($query, $this->_mailbox) as $ob) {
262:                     $this->_sorted = array_merge($this->_sorted, $ob->uids);
263:                     $this->_sortedMbox = array_merge($this->_sortedMbox, array_fill(0, count($ob->uids), strval($ob->mbox)));
264:                 }
265:             } catch (IMP_Imap_Exception $e) {
266:                 $e->notify(_("Mailbox listing failed") . ': ' . $e->getMessage());
267:             }
268:         } else {
269:             $sortpref = $this->_mailbox->getSort(true);
270:             if ($sortpref['by'] == Horde_Imap_Client::SORT_THREAD) {
271:                 $this->_threadob = null;
272:                 $threadob = $this->getThreadOb();
273:                 $this->_sorted = $threadob->messageList();
274:                 if ($sortpref['dir']) {
275:                     $this->_sorted = array_reverse($this->_sorted);
276:                 }
277:             } else {
278:                 if ($this->_mailbox->hideDeletedMsgs()) {
279:                     $query = new Horde_Imap_Client_Search_Query();
280:                     $query->flag(Horde_Imap_Client::FLAG_DELETED, false);
281:                 }
282:                 try {
283:                     $res = $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create()->search($this->_mailbox, $query, array(
284:                         'sort' => array($sortpref['by'])
285:                     ));
286:                     if ($sortpref['dir']) {
287:                         $res['match']->reverse();
288:                     }
289:                     $this->_sorted = $res['match']->ids;
290:                 } catch (IMP_Imap_Exception $e) {
291:                     $e->notify(_("Mailbox listing failed") . ': ' . $e->getMessage());
292:                 }
293:             }
294:         }
295:     }
296: 
297:     /**
298:      * Get the list of new messages in the mailbox (IMAP RECENT flag, with
299:      * UNDELETED if we're hiding deleted messages).
300:      *
301:      * @param integer $results  A Horde_Imap_Client::SORT_* constant that
302:      *                          indicates the desired return type.
303:      * @param boolean $uid      Return UIDs instead of sequence numbers (for
304:      *                          $results queries that return message lists).
305:      *
306:      * @return mixed  Whatever is requested in $results.
307:      */
308:     public function newMessages($results, $uid = false)
309:     {
310:         return $this->_msgFlagSearch('recent', $results, $uid);
311:     }
312: 
313:     /**
314:      * Get the list of unseen messages in the mailbox (IMAP UNSEEN flag, with
315:      * UNDELETED if we're hiding deleted messages).
316:      *
317:      * @param integer $results  A Horde_Imap_Client::SORT_RESULTS_* constant
318:      *                          that indicates the desired return type.
319:      * @param boolean $uid      Return UIDs instead of sequence numbers (for
320:      *                          $results queries that return message lists).
321:      *
322:      * @return mixed  Whatever is requested in $results.
323:      */
324:     public function unseenMessages($results, $uid = false)
325:     {
326:         return $this->_msgFlagSearch('unseen', $results, $uid);
327:     }
328: 
329:     /**
330:      * Do a search on a mailbox in the most efficient way available.
331:      *
332:      * @param string $type      The search type - either 'recent' or 'unseen'.
333:      * @param integer $results  A Horde_Imap_Client::SORT_RESULTS_* constant
334:      *                          that indicates the desired return type.
335:      * @param boolean $uid      Return UIDs instead of sequence numbers (for
336:      *                          $results queries that return message lists).
337:      *
338:      * @return mixed  Whatever is requested in $results.
339:      */
340:     protected function _msgFlagSearch($type, $results, $uid)
341:     {
342:         $count = ($results == Horde_Imap_Client::SORT_RESULTS_COUNT);
343: 
344:         if ($this->_mailbox->search || empty($this->_sorted)) {
345:             if ($count &&
346:                 ($type == 'unseen') &&
347:                 $this->_mailbox->vinbox) {
348:                 return count($this);
349:             }
350: 
351:             return $count ? 0 : array();
352:         }
353: 
354:         $criteria = new Horde_Imap_Client_Search_Query();
355:         $imp_imap = $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create();
356: 
357:         if ($this->_mailbox->hideDeletedMsgs()) {
358:             $criteria->flag(Horde_Imap_Client::FLAG_DELETED, false);
359:         } elseif ($count) {
360:             try {
361:                 $status_res = $imp_imap->status($this->_mailbox, $type == 'recent' ? Horde_Imap_Client::STATUS_RECENT : Horde_Imap_Client::STATUS_UNSEEN);
362:                 return $status_res[$type];
363:             } catch (IMP_Imap_Exception $e) {
364:                 return 0;
365:             }
366:         }
367: 
368:         if ($type == 'recent') {
369:             $criteria->flag(Horde_Imap_Client::FLAG_RECENT, true);
370:         } else {
371:             $criteria->flag(Horde_Imap_Client::FLAG_SEEN, false);
372:         }
373: 
374:         try {
375:             $res = $imp_imap->search($this->_mailbox, $criteria, array(
376:                 'results' => array($results),
377:                 'sequence' => !$uid
378:             ));
379:             return $count ? $res['count'] : $res;
380:         } catch (IMP_Imap_Exception $e) {
381:             return $count ? 0 : array();
382:         }
383:     }
384: 
385:     /**
386:      * Using the preferences and the current mailbox, determines the messages
387:      * to view on the current page.
388:      *
389:      * @param integer $page   The page number currently being displayed.
390:      * @param integer $start  The starting message number.
391:      *
392:      * @return array  An array with the following fields:
393:      *   anymsg: (boolean) Are there any messages at all in mailbox? E.g. If
394:      *           'msgcount' is 0, there may still be hidden deleted messages.
395:      *   begin: (integer) The beginning message sequence number of the page.
396:      *   end: (integer) The ending message sequence number of the page.
397:      *   index: (integer) The index of the starting message.
398:      *   msgcount: (integer) The number of viewable messages in the current
399:      *             mailbox.
400:      *   page: (integer) The current page number.
401:      *   pagecount: (integer) The number of pages in this mailbox.
402:      */
403:     public function buildMailboxPage($page = 0, $start = 0, $opts = array())
404:     {
405:         $this->_buildMailbox();
406: 
407:         $ret = array('msgcount' => count($this->_sorted));
408: 
409:         $page_size = max($GLOBALS['prefs']->getValue('max_msgs'), 1);
410: 
411:         if ($ret['msgcount'] > $page_size) {
412:             $ret['pagecount'] = ceil($ret['msgcount'] / $page_size);
413: 
414:             /* Determine which page to display. */
415:             if (empty($page) || strcspn($page, '0123456789')) {
416:                 if (!empty($start)) {
417:                     /* Messages set this when returning to a mailbox. */
418:                     $page = ceil($start / $page_size);
419:                 } else {
420:                     /* Search for the last visited page first. */
421:                     if ($GLOBALS['session']->exists('imp', 'mbox_page/' . $this->_mailbox)) {
422:                         $page = $GLOBALS['session']->get('imp', 'mbox_page/' . $this->_mailbox);
423:                     } elseif ($this->_mailbox->search) {
424:                         $page = 1;
425:                     } else {
426:                         $page = ceil($this->mailboxStart($ret['msgcount']) / $page_size);
427:                     }
428:                 }
429:             }
430: 
431:             /* Make sure we're not past the end or before the beginning, and
432:                that we have an integer value. */
433:             $ret['page'] = intval($page);
434:             if ($ret['page'] > $ret['pagecount']) {
435:                 $ret['page'] = $ret['pagecount'];
436:             } elseif ($ret['page'] < 1) {
437:                 $ret['page'] = 1;
438:             }
439: 
440:             $ret['begin'] = (($ret['page'] - 1) * $page_size) + 1;
441:             $ret['end'] = $ret['begin'] + $page_size - 1;
442:             if ($ret['end'] > $ret['msgcount']) {
443:                 $ret['end'] = $ret['msgcount'];
444:             }
445:         } else {
446:             $ret['begin'] = 1;
447:             $ret['end'] = $ret['msgcount'];
448:             $ret['page'] = 1;
449:             $ret['pagecount'] = 1;
450:         }
451: 
452:         $ret['index'] = $ret['begin'] - 1;
453: 
454:         /* If there are no viewable messages, check for deleted messages in
455:            the mailbox. */
456:         $ret['anymsg'] = true;
457:         if (!$ret['msgcount'] && !$this->_mailbox->search) {
458:             try {
459:                 $status = $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create()->status($this->_mailbox, Horde_Imap_Client::STATUS_MESSAGES);
460:                 $ret['anymsg'] = (bool)$status['messages'];
461:             } catch (IMP_Imap_Exception $e) {
462:                 $ret['anymsg'] = false;
463:             }
464:         }
465: 
466:         /* Store the page value now. */
467:         $GLOBALS['session']->set('imp', 'mbox_page/' . $this->_mailbox, $ret['page']);
468: 
469:         return $ret;
470:     }
471: 
472:     /**
473:      * Determines the sequence number of the first message to display, based
474:      * on the user's preferences.
475:      *
476:      * @param integer $total  The total number of messages in the mailbox.
477:      *
478:      * @return integer  The sequence number in the sorted mailbox.
479:      */
480:     public function mailboxStart($total)
481:     {
482:         if ($this->_mailbox->search) {
483:             return 1;
484:         }
485: 
486:         switch ($GLOBALS['prefs']->getValue('mailbox_start')) {
487:         case IMP::MAILBOX_START_FIRSTPAGE:
488:             return 1;
489: 
490:         case IMP::MAILBOX_START_LASTPAGE:
491:             return $total;
492: 
493:         case IMP::MAILBOX_START_FIRSTUNSEEN:
494:             if (!$this->_mailbox->access_sort) {
495:                 return 1;
496:             }
497: 
498:             $sortpref = $this->_mailbox->getSort();
499: 
500:             /* Optimization: if sorting by sequence then first unseen
501:              * information is returned via a SELECT/EXAMINE call. */
502:             if ($sortpref['by'] == Horde_Imap_Client::SORT_SEQUENCE) {
503:                 try {
504:                     $res = $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create()->status($this->_mailbox, Horde_Imap_Client::STATUS_FIRSTUNSEEN | Horde_Imap_Client::STATUS_MESSAGES);
505:                     if (!is_null($res['firstunseen'])) {
506:                         return $sortpref['dir']
507:                             ? ($res['messages'] - $res['firstunseen'] + 1)
508:                             : $res['firstunseen'];
509:                     }
510:                 } catch (IMP_Imap_Exception $e) {}
511: 
512:                 return 1;
513:             }
514: 
515:             $unseen_msgs = $this->unseenMessages(Horde_Imap_Client::SORT_RESULTS_MIN, true);
516:             return empty($unseen_msgs['min'])
517:                 ? 1
518:                 : ($this->getArrayIndex($unseen_msgs['min']) + 1);
519: 
520:         case IMP::MAILBOX_START_LASTUNSEEN:
521:             if (!$this->_mailbox->access_sort) {
522:                 return 1;
523:             }
524: 
525:             $unseen_msgs = $this->unseenMessages(Horde_Imap_Client::SORT_RESULTS_MAX, true);
526:             return empty($unseen_msgs['max'])
527:                 ? 1
528:                 : ($this->getArrayIndex($unseen_msgs['max']) + 1);
529:         }
530:     }
531: 
532:     /**
533:      * Get the thread object for the current mailbox.
534:      *
535:      * @return Horde_Imap_Client_Data_Thread  The thread object for the
536:      *                                        current mailbox.
537:      */
538:     public function getThreadOb()
539:     {
540:         if (is_null($this->_threadob)) {
541:             try {
542:                 $this->_threadob = $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create()->thread($this->_mailbox, array('criteria' => $GLOBALS['session']->get('imp', 'imap_thread')));
543:             } catch (IMP_Imap_Exception $e) {
544:                 $e->notify();
545:                 return new Horde_Imap_Client_Data_Thread(array(), 'uid');
546:             }
547:         }
548: 
549:         return $this->_threadob;
550:     }
551: 
552:     /**
553:      * Rebuilds the mailbox.
554:      */
555:     public function rebuild()
556:     {
557:         $this->_sorted = null;
558:         $this->_buildMailbox();
559:     }
560: 
561:     /**
562:      * Returns the array index of the given message UID.
563:      *
564:      * @param integer $uid   The message UID.
565:      * @param integer $mbox  The message mailbox (defaults to the current
566:      *                       mailbox).
567:      *
568:      * @return mixed  The array index of the location of the message UID in
569:      *                the current mailbox. Returns null if not found.
570:      */
571:     public function getArrayIndex($uid, $mbox = null)
572:     {
573:         $aindex = null;
574: 
575:         $this->_buildMailbox();
576: 
577:         if ($this->_mailbox->search) {
578:             if (is_null($mbox)) {
579:                 $mbox = IMP::$thismailbox;
580:             }
581: 
582:             /* Need to compare both mbox name and message UID to obtain the
583:              * correct array index since there may be duplicate UIDs. */
584:             foreach (array_keys($this->_sorted, $uid) as $key) {
585:                 if ($this->_sortedMbox[$key] == $mbox) {
586:                     return $key;
587:                 }
588:             }
589:         } else {
590:             /* array_search() returns false on no result. We will set an
591:              * unsuccessful result to NULL. */
592:             if (($aindex = array_search($uid, $this->_sorted)) === false) {
593:                 $aindex = null;
594:             }
595:         }
596: 
597:         return $aindex;
598:     }
599: 
600:     /**
601:      * Generate an IMP_Indices object out of the contents of this mailbox.
602:      *
603:      * @return IMP_Indices  An indices object.
604:      */
605:     public function getIndicesOb()
606:     {
607:         $this->_buildMailbox();
608:         $ob = new IMP_Indices();
609: 
610:         if ($this->_mailbox->search) {
611:             reset($this->_sorted);
612:             while (list($k, $v) = each($this->_sorted)) {
613:                 $ob->add($this->_sortedMbox[$k], $v);
614:             }
615:         } else {
616:             $ob->add($this->_mailbox, $this->_sorted);
617:         }
618: 
619:         return $ob;
620:     }
621: 
622:     /**
623:      * Removes messages from the mailbox.
624:      *
625:      * @param mixed $indices  An IMP_Indices object or true to remove all
626:      *                        messages in the mailbox.
627:      *
628:      * @return boolean  True if the message was removed from the mailbox.
629:      */
630:     public function removeMsgs($indices)
631:     {
632:         if ($indices === true) {
633:             $this->rebuild();
634:             return false;
635:         }
636: 
637:         if (!count($indices)) {
638:             return false;
639:         }
640: 
641:         /* Remove the current entry and recalculate the range. */
642:         foreach ($indices as $ob) {
643:             foreach ($ob->uids as $uid) {
644:                 $val = $this->getArrayIndex($uid, $ob->mbox);
645:                 unset($this->_sorted[$val]);
646:                 if ($this->_mailbox->search) {
647:                     unset($this->_sortedMbox[$val]);
648:                 }
649:             }
650:         }
651: 
652:         $this->changed = true;
653:         $this->_sorted = array_values($this->_sorted);
654:         if ($this->_mailbox->search) {
655:             $this->_sortedMbox = array_values($this->_sortedMbox);
656:         }
657:         $this->_threadob = null;
658: 
659:         return true;
660:     }
661: 
662:     /* ArrayAccess methods. */
663: 
664:     /**
665:      * @param integer $offset  Sequence number of message.
666:      */
667:     public function offsetExists($offset)
668:     {
669:         return isset($this->_sorted[$offset - 1]);
670:     }
671: 
672:     /**
673:      * @param integer $offset  Sequence number of message.
674:      *
675:      * @return array  Two-element array:
676:      *   - m: (IMP_Mailbox) Mailbox of message.
677:      *   - u: (string) UID of message.
678:      */
679:     public function offsetGet($offset)
680:     {
681:         return isset($this->_sorted[$offset - 1])
682:             ? array(
683:                   'm' => (empty($this->_sortedMbox) ? $this->_mailbox : IMP_Mailbox::get($this->_sortedMbox[$offset - 1])),
684:                   'u' => $this->_sorted[$offset - 1]
685:               )
686:             : null;
687:     }
688: 
689:     /**
690:      * @throws BadMethodCallException
691:      */
692:     public function offsetSet($offset, $value)
693:     {
694:         throw new BadMethodCallException('Not supported');
695:     }
696: 
697:     /**
698:      * @throws BadMethodCallException
699:      */
700:     public function offsetUnset($offset)
701:     {
702:         throw new BadMethodCallException('Not supported');
703:     }
704: 
705:     /* Countable methods. */
706: 
707:     /**
708:      * Returns the current message count of the mailbox.
709:      *
710:      * @return integer  The mailbox message count.
711:      */
712:     public function count()
713:     {
714:         $this->_buildMailbox();
715:         return count($this->_sorted);
716:     }
717: 
718:     /* Iterator methods. */
719: 
720:     /**
721:      * @return array  Two-element array:
722:      *   - m: (IMP_Mailbox) Mailbox of message.
723:      *   - u: (string) UID of message.
724:      */
725:     public function current()
726:     {
727:         $key = key($this->_sorted);
728:         return array(
729:             'm' => (empty($this->_sortedMbox) ? $this->_mailbox : IMP_Mailbox::get($this->_sortedMbox[$key])),
730:             'u' => $this->_sorted[$key]
731:         );
732:     }
733: 
734:     /**
735:      * @return integer  Sequence number of message.
736:      */
737:     public function key()
738:     {
739:         return (key($this->_sorted) + 1);
740:     }
741: 
742:     /**
743:      */
744:     public function next()
745:     {
746:         next($this->_sorted);
747:     }
748: 
749:     /**
750:      */
751:     public function rewind()
752:     {
753:         reset($this->_sorted);
754:     }
755: 
756:     /**
757:      */
758:     public function valid()
759:     {
760:         return (key($this->_sorted) !== null);
761:     }
762: 
763:     /* Serializable methods. */
764: 
765:     /**
766:      * Serialization.
767:      *
768:      * @return string  Serialized data.
769:      */
770:     public function serialize()
771:     {
772:         $data = array(
773:             'm' => $this->_mailbox,
774:             'v' => self::VERSION
775:         );
776: 
777:         if (!is_null($this->_sorted)) {
778:             $data['so'] = $this->_sorted;
779:             if (!empty($this->_sortedMbox)) {
780:                 $data['som'] = $this->_sortedMbox;
781:             }
782:         }
783: 
784:         foreach ($this->_slist as $val) {
785:             $data[$val] = $this->$val;
786:         }
787: 
788:         return serialize($data);
789:     }
790: 
791:     /**
792:      * Unserialization.
793:      *
794:      * @param string $data  Serialized data.
795:      *
796:      * @throws Exception
797:      */
798:     public function unserialize($data)
799:     {
800:         $data = @unserialize($data);
801:         if (!is_array($data) ||
802:             !isset($data['v']) ||
803:             ($data['v'] != self::VERSION)) {
804:             throw new Exception('Cache version change');
805:         }
806: 
807:         $this->_mailbox = $data['m'];
808: 
809:         if (isset($data['so'])) {
810:             $this->_sorted = $data['so'];
811:             if (isset($data['som'])) {
812:                 $this->_sortedMbox = $data['som'];
813:             }
814:         }
815: 
816:         foreach ($this->_slist as $val) {
817:             $this->$val = $data[$val];
818:         }
819:     }
820: 
821: }
822: 
API documentation generated by ApiGen