Platform  3.1
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
fullsearchresult.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @license http://creativecommons.org/licenses/by-nc-sa/2.0/fr/ Anakeen - licence CC
5  * @package FDL
6 */
7 /**
8  * Full Text Search document
9  *
10  * @author Anakeen 2007
11  * @version $Id: fullsearch.php,v 1.10 2008/01/04 17:56:37 eric Exp $
12  * @license http://creativecommons.org/licenses/by-nc-sa/2.0/fr/ Anakeen - licence CC
13  * @package FDL
14  * @subpackage GED
15  */
16 /**
17  */
18 
19 include_once ("FDL/Class.SearchDoc.php");
20 include_once ("FDL/Class.DocSearch.php");
21 
22 include_once ("FDL/freedom_util.php");
23 /**
24  * Fulltext Search document
25  * @param Action &$action current action
26  * @global keyword Http var : word to search in any values
27  * @global famid Http var : restrict to this family identioficator
28  * @global start Http var : page number
29  * @global dirid Http var : search identificator
30  */
32 {
33 
34  $famid = GetHttpVars("famid", 0);
35  $keyword = GetHttpVars("_se_key", GetHttpVars("keyword")); // keyword to search
36  $target = GetHttpVars("target"); // target window when click on document
37  $page = GetHttpVars("page", 0); // page number
38  $dirid = GetHttpVars("dirid", 0); // special search
39  $slice = 10;
40  $start = $page * $slice;
41 
42  $action->lay->set("isdetail", false);
43  $action->lay->set("page", $page + 1);
44  $action->lay->set("dirid", $dirid);
45  $action->lay->set("SUBSEARCH", ($start > 0));
46  $initpage = false;
47  $action->parent->AddJsRef($action->GetParam("CORE_JSURL") . "/resizeimg.js");
48  $orderby = "title";
49  $dbaccess = $action->GetParam("FREEDOM_DB");
50  if (!is_numeric($famid)) $famid = getFamIdFromName($dbaccess, $famid);
51 
52  if ($detailsearch) {
53  $search = createTmpDoc($dbaccess, 16);
54 
55  $search->setValue("se_famid", $famid);
56  $search->setValue("se_latest", "yes");
57  $search->lay = $action->lay;
58  $search->editdsearch();
59  }
60  $fdoc = new_doc($dbaccess, $famid);
61  $nosearch = false;
62  if (($keyword == "") && ($dirid == 0) && ($famid == 0)) {
63  if ($initpage) {
64  $action->lay = new Layout(getLayoutFile("FGSEARCH", "fullsearch_empty.xml") , $action);
65  return;
66  }
67  $nosearch = true;
68  }
69  $action->lay->set("INITSEARCH", $nosearch);
70  $kfams = array();
71  $fkeyword = $keyword;
72  if ($keyword != "") {
73  // process family specification
74  $kl = explode(":", $keyword);
75  if (count($kl) > 1) {
76  $keyword = $kl[1];
77  $faml = $kl[0];
78  $tf = explode(",", $faml);
79  foreach ($tf as $k => $v) {
80  if ($v == "") continue;
81  $v = trim($v);
82  if ($v[0] != "~") {
83  $b = true;
84  $n = $v;
85  } else {
86  $b = false;
87  $n = substr($v, 1);
88  }
89  $kfams[] = array(
90  "include" => $b,
91  "kfam" => $n
92  );
93  }
94  }
95  }
96  /* $bfam = array(); */
97  $tclassdoc = GetClassesDoc($dbaccess, $action->user->id, array(
98  1,
99  2
100  ) , "TABLE");
101  if (!$nosearch) {
102 
103  $sqlfilters = array();
104  $famfilter = $or = $and = "";
105  if (count($kfams) > 0) {
106  $famid = 0;
107  $tmpdoc = new Doc($dbaccess);
108  foreach ($kfams as $k => $v) {
109  foreach ($tclassdoc as $kdoc => $cdoc) {
110  if (strstr(strtolower($cdoc["title"]) , $v["kfam"]) != false) {
111  if ($v["include"]) $or.= ($or != "" ? " OR " : "") . "(fromid" . ($v["include"] ? "=" : "!=") . $cdoc["initid"] . ")";
112  else $and.= ($and != "" ? " AND " : "") . "(fromid" . ($v["include"] ? "=" : "!=") . $cdoc["initid"] . ")";
113  }
114  }
115  }
116  if ($or != "") $famfilter = "($or)";
117  if ($and != "") $famfilter.= ($famfilter != "" ? " AND " : "") . " ($and)";
118  }
119 
120  if ($keyword != "") {
121  if ($keyword[0] == '~') {
122  $sqlfilters[] = "svalues ~* '" . pg_escape_string(substr($keyword, 1)) . "'";
123  } else {
124  DocSearch::getFullSqlFilters($keyword, $sqlfilters, $orderby, $keys);
125  }
126  } else {
127  $sdoc = new_doc($dbaccess, $dirid);
128  $tkeys = $sdoc->getTValue("se_keys");
129  foreach ($tkeys as $k => $v) if (!$v) unset($tkeys[$k]);
130  $keys = implode('|', $tkeys);
131  }
132  if ($famfilter != "") $sqlfilters[] = $famfilter;
133 
134  $s = new SearchDoc($dbaccess, $famid);
135  if ($dirid) {
136  $s->useCollection($dirid);
137  $vardids = "did_$dirid";
138  } else {
139  $vardids = "did_$famid$keys";
140  foreach ($sqlfilters as $filter) {
141  $s->addFilter($filter);
142  }
143  }
144  $displayedIds = array();
145  if ($start > 0) {
146  $displayedIds = $action->read($vardids);
147  if ($displayedIds && count($displayedIds) > 0) {
148  $sqlExclude = sprintf("initid not in (%s)", implode(",", $displayedIds));
149  $s->addFilter($sqlExclude);
150  } else {
151  $s->setStart($start);
152  }
153  }
154  $s->setOrder($orderby . ', id desc');
155  $s->setSlice($slice + 1);
156  $s->excludeConfidential();
157 
158  $tdocs = $s->search();
159  if ($s->getError()) addLogMsg($s->getSearchInfo());
160  //print_r2($s->getSearchInfo());
161  if ($start == 0) {
162  if ($s->count() < ($slice + 1)) $globalCount = $s->count();
163  else {
164  $sc = new SearchDoc($dbaccess, $famid);
165  if ($dirid) {
166  $sc->useCollection($dirid);
167  } else {
168  foreach ($sqlfilters as $filter) $sc->addFilter($filter);
169  }
170  $sc->excludeConfidential();
171  $globalCount = $sc->onlyCount();
172  }
173  }
174 
175  $workdoc = new Doc($dbaccess);
176  if ($famid) $famtitle = $workdoc->getTitle($famid);
177  else $famtitle = "";
179  if ($s->count() == ($slice + 1)) {
180  array_pop($tdocs);
181  $action->lay->set("notthenend", true);
182  } else {
183  $action->lay->set("notthenend", false);
184  }
185 
186  $action->lay->set("notfirst", ($start != 0));
187  $action->lay->set("theFollowingText", _("View next results"));
188  $c = 0;
189  foreach ($tdocs as $k => $tdoc) {
190  if ($tdoc["confidential"]) {
191  if (($tdoc["profid"] > 0) && ($workdoc->controlId($tdoc["profid"], "confidential") != "")) {
192  unset($tdocs[$k]);
193  continue;
194  }
195  }
196  $displayedIds[] = $tdoc["initid"];
197  $c++;
198  $tdocs[$k]["number"] = $c + $start;
199  $tdoc["values"].= getFileTxt($dbid, $tdoc);
200  $tdocs[$k]["htext"] = nl2br(str_replace(array(
201  '[b]',
202  '[/b]',
203  ) , array(
204  '<b>',
205  '</b>'
206  ) , (str_replace("<", "&lt;", preg_replace("/<\\/?(\\w+[^:]?|\\w+\\s.*?)>/", "", str_replace(array(
207  '<b>',
208  '</b>'
209  ) , array(
210  '[b]',
211  '[/b]'
212  ) , nl2br(wordwrap(nobr(highlight_text($dbid, $tdoc["values"], $keys) , 80)))))))));
213  $tdocs[$k]["iconsrc"] = $workdoc->getIcon($tdoc["icon"]);
214  $tdocs[$k]["mdate"] = strftime("%a %d %b %Y", $tdoc["revdate"]);
215  }
216  $action->register($vardids, $displayedIds);
217 
218  if ($start > 0) {
219  for ($i = 0; $i < $start; $i+= $slice) {
220  $tpages[] = array(
221  "xpage" => $i / $slice + 1,
222  "xstart" => $i
223  );
224  }
225 
226  $action->lay->setBlockData("PAGES", $tpages);
227  }
228 
229  $action->lay->setBlockData("DOCS", $tdocs);
230 
231  $action->lay->set("dirid", $dirid);
232  if ($dirid != 0) {
233  $sdoc = new_doc($dbaccess, $dirid);
234  if ($sdoc->isAffected()) {
235  $action->lay->set("isdetail", false);
236  $action->lay->set("searchtitle", $sdoc->title);
237  $action->lay->set("dirid", $sdoc->id);
238  }
239  }
240  } else {
241  $action->lay->set("cpage", "0");
242  $action->lay->set("notfirst", false);
243  $action->lay->set("notthenend", false);
244  }
245  $action->lay->set("famid", $famid);
246  $action->lay->set("searchtitle", sprintf(_("Search %s") , $keyword));
247  if ($fkeyword == "") $action->lay->set("key", _("search dynacase documents"));
248  else $action->lay->set("key", str_replace("\"", "&quot;", $fkeyword));
249 
250  $famsuffix = ($famid == 0 ? "" : sprintf("<span class=\"families\">(%s %s)</span>", _("family search result") , $famtitle));
251  if ($globalCount == 0) {
252  $action->lay->set("resulttext", sprintf(_("No document found for <b>%s</b>%s") , $keyword, $famsuffix));
253  } else if ($globalCount == 1) {
254  $action->lay->set("resulttext", sprintf(_("One document for <b>%s</b>%s") , $keyword, $famsuffix));
255  } else {
256  $action->lay->set("resulttext", sprintf(_("Found <b>%d</b> Result for <b>%s</b>%s") , $globalCount, $keyword, $famsuffix));
257  }
258  $action->lay->set("displayBottomBar", ($globalCount == 0 ? false : true));
259  $action->lay->set("displayTopBar", ($page == 0));
260 
261  foreach ($tclassdoc as $k => $cdoc) {
262  $selectclass[$k]["idcdoc"] = $cdoc["initid"];
263  $selectclass[$k]["classname"] = $cdoc["title"];
264  $selectclass[$k]["famselect"] = ($cdoc["initid"] == $famid) ? "selected" : "";
265  }
266  $action->lay->SetBlockData("SELECTCLASS", $selectclass);
267  $action->lay->set("searchdate", Doc::getDate(0, 0, 0, 0, true));
268 }
269 /**
270  * return file text values from _txt column
271  */
272 function getFileTxt($dbid, &$tdoc)
273 {
274 
275  $sqlselect = 'svalues';
276  $sqlfrom = 'doc' . $tdoc["fromid"];
277  $sqlwhere = 'id=' . $tdoc["id"];
278 
279  $result = pg_query($dbid, "select $sqlselect from $sqlfrom where $sqlwhere ;");
280  if (pg_numrows($result) > 0) {
281  $arr = pg_fetch_array($result, 0, PGSQL_ASSOC);
282  return implode(' - ', $arr);
283  }
284 }
285 function strtr8($s, $c1, $c2)
286 {
287  $s9 = utf8_decode($s);
288  $s9 = strtr($s9, utf8_decode($c1) , utf8_decode($c2));
289  return utf8_encode($s9);
290 }
291 /**
292  * return part of text where are found keywords
293  * Due to unaccent fulltext vectorisation need to transpose original text with highlight text done by headline tsearch2 sql function
294  * @param resource $dbid database access
295  * @param string $s original text
296  * @param string $k keywords
297  * @return string HTML text with <b> tags
298  */
299 function highlight_text($dbid, &$s, $k)
300 {
301  if ($k == "") {
302  $h = str_replace('£', ' - ', substr($s, 0, 100));
303  $pos1 = mb_strpos($h, ' ');
304  $pos2 = mb_strrpos($h, ' ');
305  $headline = substr($h, $pos1, ($pos2 - $pos1));
306  } else if ((strlen($s) / 1024) > getParam("FULLTEXT_HIGHTLIGHTSIZE", 200)) {
307  $headline = sprintf(_("document too big (%dKo): no highlight") , (strlen($s) / 1024));
308  } else {
309  $s = strtr8($s, "£", " ");
310  $result = pg_query($dbid, "select ts_headline('french','" . pg_escape_string(unaccent($s)) . "',to_tsquery('french','$k'))");
311  if (pg_numrows($result) > 0) {
312  $arr = pg_fetch_array($result, 0, PGSQL_ASSOC);
313  $headline = $arr["ts_headline"];
314  }
315  // $headline=str_replace(' ',' ',$headline);
316  $headline = preg_replace('/[ ]+ /', ' ', $headline);
317  $headline = str_replace(array(
318  " \r",
319  "\n "
320  ) , array(
321  '',
322  "\n"
323  ) , $headline);
324  $pos = mb_strpos($headline, '<b>');
325  // print "<hr> POSBEG:".$pos;
326  if ($pos !== false) {
327  $sw = (str_replace(array(
328  "<b>",
329  "</b>"
330  ) , array(
331  '',
332  ''
333  ) , $headline));
334  $s = preg_replace('/[ ]+ /', ' ', $s);
335  $s = preg_replace('/<[a-z][^>]+>/', '', $s);
336  $s = str_replace(array(
337  "<br />",
338  "\r"
339  ) , array(
340  '',
341  ''
342  ) , $s);
343  $offset = mb_strpos($s, $sw);
344 
345  if ($offset === false) return $headline; // case mismatch in characters
346  $before = 20; // 20 characters before;
347  if (($pos + $offset) < $before) $p0 = 0;
348  else $p0 = $pos + $offset - $before;
349  $h = mb_substr($s, $p0, $pos + $offset - $p0); // begin of text
350  $possp = mb_strpos($h, ' ');
351  if ($possp > 0) $h = mb_substr($h, $possp); // first word
352  $pe = mb_strpos($headline, '</b>', $pos);
353  if ($pe > 0) {
354  $h.= "<b>";
355  $h.= mb_substr($s, $pos + $offset, $pe - $pos - 3);
356  $h.= "</b>";
357  }
358  // print "<br> POS:$pos [ $pos : $pe ]";
359  $pos = $pe + 1;
360  $i = 1;
361  // 7 is strlen('<b></b>');
362  while ($pe > 0) {
363  $pb = mb_strpos($headline, '<b>', $pos);
364  $pe = mb_strpos($headline, '</b>', $pos);
365  // print "<br> POS:$pos [ $pb : $pe ]";
366  if (($pe) && ($pb < $pe)) {
367  $pb--;
368  $pe; //
369  $h.= mb_substr($s, $pos - 4 - (7 * ($i - 1)) + $offset, $pb - $pos - 3);
370  $h.= "<b>";
371  $h.= mb_substr($s, $pb - (7 * $i) + $offset, $pe - $pb - 3);
372  $h.= "</b>";
373  $pos = $pe + 1;
374  $i++;
375  } else {
376  $cur = $pos - (7 * $i) + 3 + $offset;
377  if (($cur - $offset) > 150) $pend = 30;
378  else $pend = 180 - $cur + $offset;
379  $send = mb_substr($s, $cur, $pend);
380  $possp = mb_strrpos($send, ' ');
381  $send = mb_substr($send, 0, $possp);
382  $pe = 0;
383  $h.= $send;
384  // print "<br> POSEND: $cur $pend";
385 
386  }
387  }
388  //print "<br>[$headline]";
389  return $h;
390  }
391  }
392  return $headline;
393 }
394 function nobr($text)
395 {
396  return strtr8(preg_replace('/<br\\s*?\/??>/i', '', $text) , "\n\t£", " -");
397 }
398 ?>
← centre documentaire © anakeen - published under CC License - Dynacase