/** * protected method for listing a set of message headers (search results) * * @param string $folder Folder name * @param int $page Current page to list * @param int $slice Number of slice items to extract from result array * * @return array Indexed array with message header objects */ protected function list_search_messages($folder, $page, $slice = 0) { if (!strlen($folder) || empty($this->search_set) || $this->search_set->is_empty()) { return array(); } // use saved messages from searching if ($this->threading) { return $this->list_search_thread_messages($folder, $page, $slice); } // search set is threaded, we need a new one if ($this->search_threads) { $this->search('', $this->search_string, $this->search_charset, $this->sort_field); } $index = clone $this->search_set; $from = ($page - 1) * $this->page_size; $to = $from + $this->page_size; // return empty array if no messages found if ($index->is_empty()) { return array(); } // quickest method (default sorting) if (!$this->search_sort_field && !$this->sort_field) { $got_index = true; } else { if ($this->search_sorted) { // SORT searching result $got_index = true; // reset search set if sorting field has been changed if ($this->sort_field && $this->search_sort_field != $this->sort_field) { $this->search('', $this->search_string, $this->search_charset, $this->sort_field); $index = clone $this->search_set; // return empty array if no messages found if ($index->is_empty()) { return array(); } } } } if ($got_index) { if ($this->sort_order != $index->get_parameters('ORDER')) { $index->revert(); } // get messages uids for one page $index->slice($from, $to - $from); if ($slice) { $index->slice(-$slice, $slice); } // fetch headers $a_index = $index->get(); $a_msg_headers = $this->fetch_headers($folder, $a_index); return array_values($a_msg_headers); } // SEARCH result, need sorting $cnt = $index->count(); // 300: experimantal value for best result if ($cnt > 300 && $cnt > $this->page_size || !$this->sort_field) { // use memory less expensive (and quick) method for big result set $index = clone $this->index('', $this->sort_field, $this->sort_order); // get messages uids for one page... $index->slice($from, min($cnt - $from, $this->page_size)); if ($slice) { $index->slice(-$slice, $slice); } // ...and fetch headers $a_index = $index->get(); $a_msg_headers = $this->fetch_headers($folder, $a_index); return array_values($a_msg_headers); } else { // for small result set we can fetch all messages headers $a_index = $index->get(); $a_msg_headers = $this->fetch_headers($folder, $a_index, false); // return empty array if no messages found if (!is_array($a_msg_headers) || empty($a_msg_headers)) { return array(); } if (!$this->check_connection()) { return array(); } // if not already sorted $a_msg_headers = $this->conn->sortHeaders($a_msg_headers, $this->sort_field, $this->sort_order); // only return the requested part of the set $slice_length = min($this->page_size, $cnt - ($to > $cnt ? $from : $to)); $a_msg_headers = array_slice(array_values($a_msg_headers), $from, $slice_length); if ($slice) { $a_msg_headers = array_slice($a_msg_headers, -$slice, $slice); } return $a_msg_headers; } }
/** * protected method for listing a set of message headers (search results) * * @param string $folder Folder name * @param int $page Current page to list * @param int $slice Number of slice items to extract from result array * * @return array Indexed array with message header objects */ protected function list_search_messages($folder, $page, $slice = 0) { if (!strlen($folder) || empty($this->search_set) || $this->search_set->is_empty()) { return array(); } // gather messages from a multi-folder search if ($this->search_set->multi) { $page_size = $this->page_size; $sort_field = $this->sort_field; $search_set = $this->search_set; // prepare paging $cnt = $search_set->count(); $from = ($page - 1) * $page_size; $to = $from + $page_size; $slice_length = min($page_size, $cnt - $from); // fetch resultset headers, sort and slice them if (!empty($sort_field) && $search_set->get_parameters('SORT') != $sort_field) { $this->sort_field = null; $this->page_size = 1000; // fetch up to 1000 matching messages per folder $this->threading = false; $a_msg_headers = array(); foreach ($search_set->sets as $resultset) { if (!$resultset->is_empty()) { $this->search_set = $resultset; $this->search_threads = $resultset instanceof rcube_result_thread; $a_headers = $this->list_search_messages($resultset->get_parameters('MAILBOX'), 1); $a_msg_headers = array_merge($a_msg_headers, $a_headers); unset($a_headers); } } // sort headers if (!empty($a_msg_headers)) { $a_msg_headers = rcube_imap_generic::sortHeaders($a_msg_headers, $sort_field, $this->sort_order); } // store (sorted) message index $search_set->set_message_index($a_msg_headers, $sort_field, $this->sort_order); // only return the requested part of the set $a_msg_headers = array_slice(array_values($a_msg_headers), $from, $slice_length); } else { if ($this->sort_order != $search_set->get_parameters('ORDER')) { $search_set->revert(); } // slice resultset first... $fetch = array(); foreach (array_slice($search_set->get(), $from, $slice_length) as $msg_id) { list($uid, $folder) = explode('-', $msg_id, 2); $fetch[$folder][] = $uid; } // ... and fetch the requested set of headers $a_msg_headers = array(); foreach ($fetch as $folder => $a_index) { $a_msg_headers = array_merge($a_msg_headers, array_values($this->fetch_headers($folder, $a_index))); } } if ($slice) { $a_msg_headers = array_slice($a_msg_headers, -$slice, $slice); } // restore members $this->sort_field = $sort_field; $this->page_size = $page_size; $this->search_set = $search_set; return $a_msg_headers; } // use saved messages from searching if ($this->threading) { return $this->list_search_thread_messages($folder, $page, $slice); } // search set is threaded, we need a new one if ($this->search_threads) { $this->search('', $this->search_string, $this->search_charset, $this->sort_field); } $index = clone $this->search_set; $from = ($page - 1) * $this->page_size; $to = $from + $this->page_size; // return empty array if no messages found if ($index->is_empty()) { return array(); } // quickest method (default sorting) if (!$this->search_sort_field && !$this->sort_field) { $got_index = true; } else { if ($this->search_sorted) { // SORT searching result $got_index = true; // reset search set if sorting field has been changed if ($this->sort_field && $this->search_sort_field != $this->sort_field) { $this->search('', $this->search_string, $this->search_charset, $this->sort_field); $index = clone $this->search_set; // return empty array if no messages found if ($index->is_empty()) { return array(); } } } } if ($got_index) { if ($this->sort_order != $index->get_parameters('ORDER')) { $index->revert(); } // get messages uids for one page $index->slice($from, $to - $from); if ($slice) { $index->slice(-$slice, $slice); } // fetch headers $a_index = $index->get(); $a_msg_headers = $this->fetch_headers($folder, $a_index); return array_values($a_msg_headers); } // SEARCH result, need sorting $cnt = $index->count(); // 300: experimantal value for best result if ($cnt > 300 && $cnt > $this->page_size || !$this->sort_field) { // use memory less expensive (and quick) method for big result set $index = clone $this->index('', $this->sort_field, $this->sort_order); // get messages uids for one page... $index->slice($from, min($cnt - $from, $this->page_size)); if ($slice) { $index->slice(-$slice, $slice); } // ...and fetch headers $a_index = $index->get(); $a_msg_headers = $this->fetch_headers($folder, $a_index); return array_values($a_msg_headers); } else { // for small result set we can fetch all messages headers $a_index = $index->get(); $a_msg_headers = $this->fetch_headers($folder, $a_index, false); // return empty array if no messages found if (!is_array($a_msg_headers) || empty($a_msg_headers)) { return array(); } // if not already sorted $a_msg_headers = rcube_imap_generic::sortHeaders($a_msg_headers, $this->sort_field, $this->sort_order); // only return the requested part of the set $slice_length = min($this->page_size, $cnt - ($to > $cnt ? $from : $to)); $a_msg_headers = array_slice(array_values($a_msg_headers), $from, $slice_length); if ($slice) { $a_msg_headers = array_slice($a_msg_headers, -$slice, $slice); } return $a_msg_headers; } }
/** * Private method for listing a set of message headers (search results) * * @param string $mailbox Mailbox/folder name * @param int $page Current page to list * @param string $sort_field Header field to sort by * @param string $sort_order Sort order [ASC|DESC] * @param int $slice Number of slice items to extract from result array * @return array Indexed array with message header objects * @access private * @see rcube_imap::list_header_set() */ private function _list_header_set($mailbox, $page = NULL, $sort_field = NULL, $sort_order = NULL, $slice = 0) { if (!strlen($mailbox) || empty($this->search_set)) { return array(); } // use saved messages from searching if ($this->threading) { return $this->_list_thread_header_set($mailbox, $page, $sort_field, $sort_order, $slice); } // search set is threaded, we need a new one if ($this->search_threads) { if (empty($this->search_set['tree'])) { return array(); } $this->search('', $this->search_string, $this->search_charset, $sort_field); } $msgs = $this->search_set; $a_msg_headers = array(); $page = $page ? $page : $this->list_page; $start_msg = ($page - 1) * $this->page_size; $this->_set_sort_order($sort_field, $sort_order); // quickest method (default sorting) if (!$this->search_sort_field && !$this->sort_field) { if ($sort_order == 'DESC') { $msgs = array_reverse($msgs); } // get messages uids for one page $msgs = array_slice(array_values($msgs), $start_msg, min(count($msgs) - $start_msg, $this->page_size)); if ($slice) { $msgs = array_slice($msgs, -$slice, $slice); } // fetch headers $this->_fetch_headers($mailbox, join(',', $msgs), $a_msg_headers, NULL); // I didn't found in RFC that FETCH always returns messages sorted by index $sorter = new rcube_header_sorter(); $sorter->set_sequence_numbers($msgs); $sorter->sort_headers($a_msg_headers); return array_values($a_msg_headers); } // sorted messages, so we can first slice array and then fetch only wanted headers if ($this->search_sorted) { // SORT searching result // reset search set if sorting field has been changed if ($this->sort_field && $this->search_sort_field != $this->sort_field) { $msgs = $this->search('', $this->search_string, $this->search_charset, $this->sort_field); } // return empty array if no messages found if (empty($msgs)) { return array(); } if ($sort_order == 'DESC') { $msgs = array_reverse($msgs); } // get messages uids for one page $msgs = array_slice(array_values($msgs), $start_msg, min(count($msgs) - $start_msg, $this->page_size)); if ($slice) { $msgs = array_slice($msgs, -$slice, $slice); } // fetch headers $this->_fetch_headers($mailbox, join(',', $msgs), $a_msg_headers, NULL); $sorter = new rcube_header_sorter(); $sorter->set_sequence_numbers($msgs); $sorter->sort_headers($a_msg_headers); return array_values($a_msg_headers); } else { // SEARCH result, need sorting $cnt = count($msgs); // 300: experimantal value for best result if ($cnt > 300 && $cnt > $this->page_size || !$this->sort_field) { // use memory less expensive (and quick) method for big result set $a_index = $this->message_index('', $this->sort_field, $this->sort_order); // get messages uids for one page... $msgs = array_slice($a_index, $start_msg, min($cnt - $start_msg, $this->page_size)); if ($slice) { $msgs = array_slice($msgs, -$slice, $slice); } // ...and fetch headers $this->_fetch_headers($mailbox, join(',', $msgs), $a_msg_headers, NULL); // return empty array if no messages found if (!is_array($a_msg_headers) || empty($a_msg_headers)) { return array(); } $sorter = new rcube_header_sorter(); $sorter->set_sequence_numbers($msgs); $sorter->sort_headers($a_msg_headers); return array_values($a_msg_headers); } else { // for small result set we can fetch all messages headers $this->_fetch_headers($mailbox, join(',', $msgs), $a_msg_headers, NULL); // return empty array if no messages found if (!is_array($a_msg_headers) || empty($a_msg_headers)) { return array(); } // if not already sorted $a_msg_headers = $this->conn->sortHeaders($a_msg_headers, $this->sort_field, $this->sort_order); // only return the requested part of the set $a_msg_headers = array_slice(array_values($a_msg_headers), $start_msg, min($cnt - $start_msg, $this->page_size)); if ($slice) { $a_msg_headers = array_slice($a_msg_headers, -$slice, $slice); } return $a_msg_headers; } } }