EGOCMS  24.0
EGOTEC Content-Managament-System
Ego_Search_Sql.php
gehe zur Dokumentation dieser Datei
1 <?php
6 require_once('base/Ego_Search.php');
7 
15 {
16  static $replace_source = array('ä', 'ö', 'ü', 'ß');
17  static $replace_target = array('ae', 'oe', 'ue', 'ß');
18  private $_table;
19  private $_count;
27  function __construct($table, $suffix='_fulltext')
28  {
29  $this->_table = $table.$suffix;
30  $this->_count = $table.'_fullnum';
31  }
32 
38  function delete($index)
39  {
40  assert(is_numeric($index));
41  $db = new_db_connection(); /* @var $db Ego_Sql_Abstract */
42  $db->delete(array(
43  'table' => $this->_table,
44  'where' => 'id='.$index,
45  'nobackup' => 1
46  ));
47 
48  $db->delete(array(
49  'table' => $this->_count,
50  'where' => 'id='.$index,
51  'nobackup' => 1
52  ));
53  return true;
54  }
55 
61  function reset()
62  {
63  if (Ego_System::getDbDriver()=='mysql')
64  {
65  throw new Exception('Die SQL Suche kann mit dem mysql Treiber nicht verwendet werden, bitte verwenden Sie den mysqli Treiber.');
66  }
67  $db = new_db_connection(); /* @var $db Ego_Sql_Abstract */
68  $db->createTable(
69  $this->_table,
70  array(
71  'name' => 'varchar(255)/*bin*/',
72  'id' => 'bigint',
73  'count' => 'int',
74  'PRIMARY KEY' => 'name,id',
75  'KEY id' => 'id'
76  )
77  );
78 
79  $db->createTable(
80  $this->_count,
81  array(
82  'id' => 'bigint',
83  'count' => 'int',
84  'PRIMARY KEY' => 'id'
85  )
86  );
87  return true;
88  }
89 
99  function update($index, $page, $count = array(), $recursive = true)
100  {
101  $count_keys = array();
102  $count_words = $this->_countAllWords($page, $count);
103 
104  foreach ($count as $k => $c)
105  {
106  // Der Wert des Feldes ist relativ zu allen Wörtern
107  $c = ceil($count_words * ($c / 100));
108 
109  // Den Inhalt an den Leerzeichen aufspalten.
110  $content_keys = explode(' ', $this->_getContent($page, $k));
111 
112  foreach ($content_keys as $key)
113  {
114  set_time_limit(0);
115  if ($key)
116  {
117  if (strlen($key)<250)
118  {
119  $key = mb_strtolower($key);
120  if ($count_keys[$key])
121  {
122  $count_keys[$key] += $c;
123  } else {
124  $count_keys[$key] = $c;
125  }
126 
127  $content2 = strtr($key,'"\'(),-+;:.#~*@_/', ' ');
128  $content_keys2 = explode(' ', $content2); // Den Inhalt an den Leerzeichen aufspalten.
129 
130  foreach ($content_keys2 as $key2)
131  {
132  set_time_limit(0);
133  if ($key2)
134  {
135  while (mb_strlen($key2)>=2)
136  {
137  if ($key!=$key2)
138  {
139  if ($count_keys[$key2])
140  {
141  $count_keys[$key2] += $c;
142  } else {
143  $count_keys[$key2] = $c;
144  }
145  }
146  $key2 = mb_substr($key2, 1);
147  }
148  }
149  }
150  }
151  }
152  }
153  }
154 
155  $this->delete($index);
156  $db = new_db_connection();
157  $db->begin();
158  foreach ($count_keys as $key => $count)
159  {
160  set_time_limit(0);
161  $db->insert(array(
162  'table' => $this->_table,
163  'set' => array('name' => $key, 'id' => $index, 'count' => $count),
164  'nobackup' => 1
165  ));
166  }
167 
168  //
169  $db->insert(array(
170  'table' => $this->_count,
171  'set' => array('id' => $index, 'count' => $count_words),
172  'nobackup' => 1
173  ));
174 
175  $db->commit();
176  return true;
177  }
178 
186  private function _countAllWords($page, $count)
187  {
188  $count_words = 0;
189 
190  foreach ($count as $k => $c)
191  {
192  $content_keys = explode(' ', $this->_getContent($page, $k)); // Den Inhalt an den Leerzeichen aufspalten.
193 
194  foreach ($content_keys as $key)
195  {
196  set_time_limit(0);
197  if ($key)
198  {
199  if (strlen($key)>=2 && strlen($key)<250)
200  {
201  $count_words++;
202  }
203  }
204  }
205  }
206 
207  return $count_words;
208  }
209 
219  function replace($part, $reverse=false)
220  {
221  if ($reverse)
222  {
224  } else {
226  }
227  }
228 
277  function search($search, $relation, $query, $use_query_andorscore=false, $id_field='id', $name_field='name',
278  $count_field='count', $cond_field='', $more_tables='', $more_where='', $score_select='', $lower=false)
279  {
280  $this->checkSearch($search);
281 
282  if ($lower)
283  {
284  $name_field = 'LOWER('.$this->_table.'.'.$name_field.')';
285  } else {
286  $name_field = $this->_table.'.'.$name_field;
287  }
288  $search = mb_strtolower(trim($search));
289  $cond_field2 = $cond_field?$cond_field:$this->_table.'.'.$id_field;
290  $search_asterix = ''; // Die Suche mit * erweitern.
291  $in_string = '';
292  $in_search = '';
293  for ($i=0; $i<strlen($search); $i++)
294  {
295  $character = $search[$i];
296  switch ($character)
297  {
298  case '"':
299  if ($in_string=='"')
300  {
301  $in_string = '';
302  if (!$query['having']) {
303  $query['having'] = "1=1";
304  }
305  $query['having'].= " AND (name LIKE :insearch OR title LIKE :insearch OR short LIKE :insearch OR content LIKE :insearch OR extra LIKE :insearch)";
306  $query['bind']['insearch'] = '%'.$in_search.'%';
307  } else
308  {
309  $in_string = '"';
310  $in_search = '';
311  $search_asterix.= '+';
312  }
313  break;
314  case ' ':
315  if (!$in_string)
316  {
317  $search_asterix.= '*';
318  }
319  $search_asterix.= $character;
320  if ($in_string) {
321  $in_search.= $character;
322  $search_asterix.= '+';
323  }
324  break;
325  default:
326  if ($in_string) {
327  $in_search.= $character;
328  }
329  $search_asterix.= $character;
330  }
331  }
332  if ($character!='"')
333  { // Am Ende noch einen Asterix hinzufügen.
334  $search_asterix.= '*';
335  }
336  $search = $search_asterix;
337 
338  $search = strtr($search, '*', '%');
339  $search = preg_replace('/\+ +/', '+', $search);
340  $search = preg_replace('/\- +/', '-', $search);
341  $parts = explode(' ', $search);
342 
343  $query_and = array();
344  $query_or = array();
345  $query_score = array();
346  $i = 0;
347  foreach($parts as $part) // Bearbeiten der einzelnen Suchbegriffsteile
348  {
349  $i++;
350  //str_replace ' => \'
351  // oder unten binds
352  //
353  $part = mb_strtolower($part, 'UTF-8'); // Groß-/Kleinschreibung ignorieren.
354  if ($part[0] == '+')
355  {
356  $part = substr($part, 1);
357  $and = $relation.' IN (SELECT '.$cond_field2.' FROM '.$this->_table.$more_tables.
358  ' WHERE '.$name_field.' LIKE :part'.$i.($more_where?' AND '.$more_where:'').')';
359  $query['bind']['part'.$i] = $part;
360  if ($use_query_andorscore)
361  {
362  $query['andor'][$part][] = $and;
363  } else {
364  $query_and[] = $and;
365  }
366  $query_score[] = $name_field.' LIKE :part'.$i;
367  } elseif ($part[0] == '-')
368  {
369  $part = substr($part, 1);
370  $and= $relation.' NOT IN (SELECT '.$cond_field2.' FROM '.$this->_table.$more_tables.
371  ' WHERE '.$name_field.' LIKE :part'.$i.($more_where?' AND '.$more_where:'').')';
372  $query['bind']['part'.$i] = $part;
373  if ($use_query_andorscore)
374  {
375  $query['and'][] = $and;
376  } else {
377  $query_and[] = $and;
378  }
379  }
380  else
381  {
382  $like = $name_field.' LIKE :part'.$i;
383  $query['bind']['part'.$i] = $part;
384  $part2 = $this->replace($part);
385  if ($part!=$part2)
386  {
387  $like2 = $name_field.' LIKE :parta'.$i;
388  $query['bind']['parta'.$i] = $part2;
389  $like = '('.$like.' OR '.$like2.')';
390  }
391  $part3 = $this->replace($part, true);
392  if ($part!=$part3)
393  {
394  $like3 = $name_field.' LIKE :partb'.$i;
395  $query['bind']['partb'.$i] = $part3;
396  $like = '('.$like.' OR '.$like3.')';
397  }
398  $query_or[] = $relation.' IN (SELECT '.$cond_field2.' FROM '.$this->_table.$more_tables.
399  ' WHERE '.$like.($more_where?' AND '.$more_where:'').')';
400  $query_score[] = $like;
401  }
402  }
403 
404  if ($query_and) // Zusammenbauen der Suchanfrage
405  {
406  $query['where'] .= "\n AND ".join(' AND ', $query_and);
407  }
408  if ($query_or)
409  {
410  if ($use_query_andorscore)
411  {
412  if (is_array($query['or']))
413  {
414  $query['or'] = array_merge($query['or'], $query_or);
415  } else {
416  $query['or'] = $query_or;
417  }
418  } else {
419  $query['where'] .= "\n AND ( (".join(') OR (', $query_or).') )';
420  }
421  }
422  if ($count_field && $query_score)
423  {
424  $score = '(SELECT SUM('.$this->_table.'.'.$count_field.') FROM '.$this->_table.' WHERE '.
425  $relation.'='.$this->_table.'.'.$id_field.' AND ('.join(' OR ',$query_score).') GROUP BY '.$this->_table.'.'.$id_field.') * '.
426  round(50/sizeof($query_score)).' / '.
427  '(SELECT '.$count_field.' FROM '.$this->_count.' WHERE '.$this->_count.'.'.$id_field.'='.$relation.')';
428  if ($use_query_andorscore)
429  {
430  $query['score'][] = $score;
431  } else {
432  $query['fields2'][] = '('.$score.') AS score';
433  }
434  if (!$query['order'])
435  {
436  $query['order'] = 'score DESC';
437  }
438  }
439  if ($score_select && $query_score)
440  {
441  $score = $score_select.' AND ('.join(' OR ',$query_score).') AND '.$relation.'='.$cond_field2;
442 
443  $query['score'] = array($score);
444 
445  if (!$query['order'])
446  {
447  $query['order'] = 'score DESC';
448  }
449  }
450  if ($this->extraQuery) {
451  if ($query['where']) {
452  $query['where'] .= " AND {$this->extraQuery}";
453  } else {
454  $query['where'] = $this->extraQuery;
455  }
456  }
457  return $query;
458  }
459 }
460 ?>
static $replace_target
replace($part, $reverse=false)
static $replace_source
__construct($table, $suffix='_fulltext')
search($search, $relation, $query, $use_query_andorscore=false, $id_field='id', $name_field='name', $count_field='count', $cond_field='', $more_tables='', $more_where='', $score_select='', $lower=false)
update($index, $page, $count=array(), $recursive=true)
checkSearch($search)
Definition: Ego_Search.php:595
_getContent($page, $k)
Definition: Ego_Search.php:166
static getDbDriver($db=null)