/** * THREAD=REFS sorting implementation (based on provided index) * * @param rcube_result_index $index Sorted message identifiers */ public function sort($index) { $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->count_messages()) { $index->intersect($this->get()); } $result = array_fill_keys($index->get(), null); $datalen = strlen($this->raw_data); $start = 0; // Here we're parsing raw_data twice, we want only one big array // in memory at a time // Assign roots while (($pos = @strpos($this->raw_data, self::SEPARATOR_ELEMENT, $start)) || $start < $datalen && ($pos = $datalen)) { $len = $pos - $start; $elem = substr($this->raw_data, $start, $len); $start = $pos + 1; $items = explode(self::SEPARATOR_ITEM, $elem); $root = (int) array_shift($items); $result[$elem] = $elem; foreach ($items as $item) { list($lv, $id) = explode(self::SEPARATOR_LEVEL, $item); $result[$id] = $root; } } // get only unique roots $result = array_filter($result); // make sure there are no nulls $result = array_unique($result, SORT_NUMERIC); // Re-sort raw data $result = array_fill_keys($result, null); $start = 0; while (($pos = @strpos($this->raw_data, self::SEPARATOR_ELEMENT, $start)) || $start < $datalen && ($pos = $datalen)) { $len = $pos - $start; $elem = substr($this->raw_data, $start, $len); $start = $pos + 1; $npos = strpos($elem, self::SEPARATOR_ITEM); $root = (int) ($npos ? substr($elem, 0, $npos) : $elem); $result[$root] = $elem; } $this->raw_data = implode(self::SEPARATOR_ELEMENT, $result); }