3 # OpenSearch backend for ErfurtWiki with MySQL database, but should also
4 # work for PhpWiki 1.2 installs (but you need to glue it yourself then).
8 #-- plugin registration
9 $wikiapi["wiki.search"] = "ewiki_opensearch_api";
13 function ewiki_opensearch_api($query, $params) {
15 #-- database connection
16 // should already be established
18 #-- check request params
19 $params = (array)$params
27 $n_hit = $params["n_hit"];
28 $q_pos = $params["q_pos"];
29 $q_not = $params["q_not"];
32 #-- search target field mapped to internal SQL row names
40 "filename" => "title",
44 #-- sort request terms into MUST and NOT ------------------------ SQL ---
49 foreach ($query as $i=>$qterm) {
50 list($pattern, $dep, $field, $flags) = $qterm;
51 $f_regex = strpos($flags, "REGEX") !== false;
52 $f_nocase = strpos($flags, "NOCASE") !== false;
53 $m_field = isset($params["m_$field"]) ? $params["m_$field"] : 0;
55 if ($field = $fieldnames[$field]) {
57 $pattern = mysql_escape_string($pattern);
60 $s = "$field REGEXP '$pattern'";
63 $pattern = strtolower($pattern);
64 $s = "LOCATE('$pattern', LCASE($field)) > 0";
67 $s = "LOCATE('$pattern', $field) > 0";
71 $sql[$dep][] = "($s)";
74 $calc[] = array($pattern, $dep, $field, $f_regex, $f_nocase, $m_field);
78 $sql_MUST = implode(" OR ", $sql["MUST"]);
82 $sql_MUST = implode(" AND ", $sql["MUST"]);
83 $sql_NOT = implode(" OR ", $sql["NOT"]);
84 if ($sql_NOT) { $sql_NOT = " AND NOT ($sql_NOT)"; }
87 #-- last validity checks
89 // no way to send an error with ED xmlrpclib ?
90 return("551: at least one MUST search term must be given");
95 $sql_DB_F_TEXT = "((flags & 1) > 0) AND";
96 $sql_query_result = mysql_query($sql="
98 pagename AS id, version AS version,
101 CONCAT(pagename, content) AS content,
114 GROUP BY id ORDER BY version
117 #-- start hit score calculation ---------------------------------- CALC ---
118 $result_list = array();
119 $ordered_list = array();
120 if ($sql_query_result) while ($row = mysql_fetch_array($sql_query_result)) {
122 $score = 0.0; // final score
123 $m_fin = 1.0; // to eventually decrease it later
125 #-- score each search term for hit
126 foreach ($calc as $qterm) {
127 list($pattern, $dep, $field, $f_regex, $f_nocase, $m_field) = $qterm;
137 $ok = preg_match($pattern, $row["field"]);
139 $score += $add * ($ok ? 1.0 : $q_not);
141 elseif ($dep=="NOT") {
149 $text = $f_nocase ? strtolower($row[$field]) : $row[$field];
150 $len = strlen($text) + 1;
152 #-- add points for each hit, weighted by match position
155 while (false !== ($p = strpos($text, $pattern, $p+1))) {
156 $score += $add * ($q_pos - ($q_pos - 1) * ($p / $len));
160 elseif (strpos($text, $pattern) !== false) {
168 if ($score *= $m_fin) {
169 $result_list[] = array(
170 "title" => $row["title"],
171 "url" => ewiki_script_url("", $row["title"]),
172 "excerpt" => substr(strtr($row["text"], "\r\n\t\f", " "), 0, 300),
174 "lastmodified" => $row["lastmodified"],
176 $ordered_list[] = $score;
181 arsort($ordered_list);
182 foreach ($ordered_list as $i=>$uu) {
183 $ordered_list[$i] = $result_list[$i];
184 unset($result_list[$i]);
186 $result_list = & $ordered_list;
190 return($ordered_list);