function BuildExcerpts($docs, $index, $words, $opts = array())
{
assert(is_array($docs));
assert(is_string($index));
assert(is_string($words));
assert(is_array($opts));
$this->_MBPush();
if (!($fp = $this->_Connect())) {
$this->_MBPop();
return false;
}
/////////////////
// fixup options
/////////////////
if (!isset($opts["before_match"])) {
$opts["before_match"] = "<b>";
}
if (!isset($opts["after_match"])) {
$opts["after_match"] = "</b>";
}
if (!isset($opts["chunk_separator"])) {
$opts["chunk_separator"] = " ... ";
}
if (!isset($opts["limit"])) {
$opts["limit"] = 256;
}
if (!isset($opts["limit_passages"])) {
$opts["limit_passages"] = 0;
}
if (!isset($opts["limit_words"])) {
$opts["limit_words"] = 0;
}
if (!isset($opts["around"])) {
$opts["around"] = 5;
}
if (!isset($opts["exact_phrase"])) {
$opts["exact_phrase"] = false;
}
if (!isset($opts["single_passage"])) {
$opts["single_passage"] = false;
}
if (!isset($opts["use_boundaries"])) {
$opts["use_boundaries"] = false;
}
if (!isset($opts["weight_order"])) {
$opts["weight_order"] = false;
}
if (!isset($opts["query_mode"])) {
$opts["query_mode"] = false;
}
if (!isset($opts["force_all_words"])) {
$opts["force_all_words"] = false;
}
if (!isset($opts["start_passage_id"])) {
$opts["start_passage_id"] = 1;
}
if (!isset($opts["load_files"])) {
$opts["load_files"] = false;
}
if (!isset($opts["html_strip_mode"])) {
$opts["html_strip_mode"] = "index";
}
if (!isset($opts["allow_empty"])) {
$opts["allow_empty"] = false;
}
if (!isset($opts["passage_boundary"])) {
$opts["passage_boundary"] = "none";
}
if (!isset($opts["emit_zones"])) {
$opts["emit_zones"] = false;
}
/////////////////
// build request
/////////////////
// v.1.2 req
$flags = 1;
// remove spaces
if ($opts["exact_phrase"]) {
$flags |= 2;
}
if ($opts["single_passage"]) {
$flags |= 4;
}
if ($opts["use_boundaries"]) {
$flags |= 8;
}
if ($opts["weight_order"]) {
$flags |= 16;
}
if ($opts["query_mode"]) {
$flags |= 32;
}
if ($opts["force_all_words"]) {
$flags |= 64;
}
if ($opts["load_files"]) {
$flags |= 128;
}
if ($opts["allow_empty"]) {
$flags |= 256;
}
if ($opts["emit_zones"]) {
$flags |= 512;
}
$req = pack("NN", 0, $flags);
// mode=0, flags=$flags
$req .= pack("N", strlen($index)) . $index;
// req index
$req .= pack("N", strlen($words)) . $words;
// req words
// options
$req .= pack("N", strlen($opts["before_match"])) . $opts["before_match"];
$req .= pack("N", strlen($opts["after_match"])) . $opts["after_match"];
$req .= pack("N", strlen($opts["chunk_separator"])) . $opts["chunk_separator"];
$req .= pack("NN", (int) $opts["limit"], (int) $opts["around"]);
$req .= pack("NNN", (int) $opts["limit_passages"], (int) $opts["limit_words"], (int) $opts["start_passage_id"]);
// v.1.2
$req .= pack("N", strlen($opts["html_strip_mode"])) . $opts["html_strip_mode"];
$req .= pack("N", strlen($opts["passage_boundary"])) . $opts["passage_boundary"];
// documents
$req .= pack("N", count($docs));
foreach ($docs as $doc) {
assert(is_string($doc));
$req .= pack("N", strlen($doc)) . $doc;
}
////////////////////////////
// send query, get response
////////////////////////////
$len = strlen($req);
$req = pack("nnN", SEARCHD_COMMAND_EXCERPT, VER_COMMAND_EXCERPT, $len) . $req;
// add header
if (!$this->_Send($fp, $req, $len + 8) || !($response = $this->_GetResponse($fp, VER_COMMAND_EXCERPT))) {
$this->_MBPop();
return false;
}
//////////////////
// parse response
//////////////////
$pos = 0;
$res = array();
$rlen = strlen($response);
for ($i = 0; $i < count($docs); $i++) {
list(, $len) = unpack("N*", substr($response, $pos, 4));
$pos += 4;
if ($pos + $len > $rlen) {
$this->_error = "incomplete reply";
$this->_MBPop();
return false;
}
$res[] = $len ? substr($response, $pos, $len) : "";
$pos += $len;
}
$this->_MBPop();
return $res;
}