EGOCMS  18.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 
97  function update($index, $page, $count = array())
98  {
99  $count_keys = array();
100  $count_words = $this->_countAllWords($page, $count);
101 
102  foreach ($count as $k => $c)
103  {
104  // Der Wert des Feldes ist relativ zu allen Wörtern
105  $c = ceil($count_words * ($c / 100));
106 
107  // Den Inhalt an den Leerzeichen aufspalten.
108  $content_keys = explode(' ', $this->_getContent($page, $k));
109 
110  foreach ($content_keys as $key)
111  {
112  set_time_limit(0);
113  if ($key)
114  {
115  if (strlen($key)<250)
116  {
117  $key = mb_strtolower($key);
118  if ($count_keys[$key])
119  {
120  $count_keys[$key] += $c;
121  } else {
122  $count_keys[$key] = $c;
123  }
124 
125  $content2 = strtr($key,'"\'(),-+;:.#~*@_/', ' ');
126  $content_keys2 = explode(' ', $content2); // Den Inhalt an den Leerzeichen aufspalten.
127 
128  foreach ($content_keys2 as $key2)
129  {
130  set_time_limit(0);
131  if ($key2)
132  {
133  while (mb_strlen($key2)>=2)
134  {
135  if ($key!=$key2)
136  {
137  if ($count_keys[$key2])
138  {
139  $count_keys[$key2] += $c;
140  } else {
141  $count_keys[$key2] = $c;
142  }
143  }
144  $key2 = mb_substr($key2, 1);
145  }
146  }
147  }
148  }
149  }
150  }
151  }
152 
153  $this->delete($index);
154  $db = new_db_connection();
155  $db->begin();
156  foreach ($count_keys as $key => $count)
157  {
158  set_time_limit(0);
159  $db->insert(array(
160  'table' => $this->_table,
161  'set' => array('name' => $key, 'id' => $index, 'count' => $count),
162  'nobackup' => 1
163  ));
164  }
165 
166  //
167  $db->insert(array(
168  'table' => $this->_count,
169  'set' => array('id' => $index, 'count' => $count_words),
170  'nobackup' => 1
171  ));
172 
173  $db->commit();
174  return true;
175  }
176 
184  private function _countAllWords($page, $count)
185  {
186  $count_words = 0;
187 
188  foreach ($count as $k => $c)
189  {
190  $content_keys = explode(' ', $this->_getContent($page, $k)); // Den Inhalt an den Leerzeichen aufspalten.
191 
192  foreach ($content_keys as $key)
193  {
194  set_time_limit(0);
195  if ($key)
196  {
197  if (strlen($key)>=2 && strlen($key)<250)
198  {
199  $count_words++;
200  }
201  }
202  }
203  }
204 
205  return $count_words;
206  }
207 
217  function replace($part, $reverse=false)
218  {
219  if ($reverse)
220  {
222  } else {
224  }
225  }
226 
275  function search($search, $relation, $query, $use_query_andorscore=false, $id_field='id', $name_field='name',
276  $count_field='count', $cond_field='', $more_tables='', $more_where='', $score_select='', $lower=false)
277  {
278  $this->checkSearch($search);
279 
280  if ($lower)
281  {
282  $name_field = 'LOWER('.$this->_table.'.'.$name_field.')';
283  } else {
284  $name_field = $this->_table.'.'.$name_field;
285  }
286  $search = mb_strtolower(trim($search));
287  $cond_field2 = $cond_field?$cond_field:$this->_table.'.'.$id_field;
288  $search_asterix = ''; // Die Suche mit * erweitern.
289  $in_string = '';
290  $in_search = '';
291  for ($i=0; $i<strlen($search); $i++)
292  {
293  $character = $search[$i];
294  switch ($character)
295  {
296  case '"':
297  if ($in_string=='"')
298  {
299  $in_string = '';
300  if (!$query['having']) {
301  $query['having'] = "1=1";
302  }
303  $query['having'].= " AND (name LIKE :insearch OR title LIKE :insearch OR short LIKE :insearch OR content LIKE :insearch OR extra LIKE :insearch)";
304  $query['bind']['insearch'] = '%'.$in_search.'%';
305  } else
306  {
307  $in_string = '"';
308  $in_search = '';
309  $search_asterix.= '+';
310  }
311  break;
312  case ' ':
313  if (!$in_string)
314  {
315  $search_asterix.= '*';
316  }
317  $search_asterix.= $character;
318  if ($in_string) {
319  $in_search.= $character;
320  $search_asterix.= '+';
321  }
322  break;
323  default:
324  if ($in_string) {
325  $in_search.= $character;
326  }
327  $search_asterix.= $character;
328  }
329  }
330  if ($character!='"')
331  { // Am Ende noch einen Asterix hinzufügen.
332  $search_asterix.= '*';
333  }
334  $search = $search_asterix;
335 
336  $search = strtr($search, '*', '%');
337  $search = preg_replace('/\+ +/', '+', $search);
338  $search = preg_replace('/\- +/', '-', $search);
339  $parts = explode(' ', $search);
340 
341  $query_and = array();
342  $query_or = array();
343  $query_score = array();
344  $i = 0;
345  foreach($parts as $part) // Bearbeiten der einzelnen Suchbegriffsteile
346  {
347  $i++;
348  //str_replace ' => \'
349  // oder unten binds
350  //
351  $part = mb_strtolower($part, 'UTF-8'); // Groß-/Kleinschreibung ignorieren.
352  if ($part[0] == '+')
353  {
354  $part = substr($part, 1);
355  $and = $relation.' IN (SELECT '.$cond_field2.' FROM '.$this->_table.$more_tables.
356  ' WHERE '.$name_field.' LIKE :part'.$i.($more_where?' AND '.$more_where:'').')';
357  $query['bind']['part'.$i] = $part;
358  if ($use_query_andorscore)
359  {
360  $query['andor'][$part][] = $and;
361  } else {
362  $query_and[] = $and;
363  }
364  $query_score[] = $name_field.' LIKE :part'.$i;
365  } elseif ($part[0] == '-')
366  {
367  $part = substr($part, 1);
368  $and= $relation.' NOT IN (SELECT '.$cond_field2.' FROM '.$this->_table.$more_tables.
369  ' WHERE '.$name_field.' LIKE :part'.$i.($more_where?' AND '.$more_where:'').')';
370  $query['bind']['part'.$i] = $part;
371  if ($use_query_andorscore)
372  {
373  $query['and'][] = $and;
374  } else {
375  $query_and[] = $and;
376  }
377  }
378  else
379  {
380  $like = $name_field.' LIKE :part'.$i;
381  $query['bind']['part'.$i] = $part;
382  $part2 = $this->replace($part);
383  if ($part!=$part2)
384  {
385  $like2 = $name_field.' LIKE :parta'.$i;
386  $query['bind']['parta'.$i] = $part2;
387  $like = '('.$like.' OR '.$like2.')';
388  }
389  $part3 = $this->replace($part, true);
390  if ($part!=$part3)
391  {
392  $like3 = $name_field.' LIKE :partb'.$i;
393  $query['bind']['partb'.$i] = $part3;
394  $like = '('.$like.' OR '.$like3.')';
395  }
396  $query_or[] = $relation.' IN (SELECT '.$cond_field2.' FROM '.$this->_table.$more_tables.
397  ' WHERE '.$like.($more_where?' AND '.$more_where:'').')';
398  $query_score[] = $like;
399  }
400  }
401 
402  if ($query_and) // Zusammenbauen der Suchanfrage
403  {
404  $query['where'] .= "\n AND ".join(' AND ', $query_and);
405  }
406  if ($query_or)
407  {
408  if ($use_query_andorscore)
409  {
410  if (is_array($query['or']))
411  {
412  $query['or'] = array_merge($query['or'], $query_or);
413  } else {
414  $query['or'] = $query_or;
415  }
416  } else {
417  $query['where'] .= "\n AND ( (".join(') OR (', $query_or).') )';
418  }
419  }
420  if ($count_field && $query_score)
421  {
422  $score = '(SELECT SUM('.$this->_table.'.'.$count_field.') FROM '.$this->_table.' WHERE '.
423  $relation.'='.$this->_table.'.'.$id_field.' AND ('.join(' OR ',$query_score).') GROUP BY '.$this->_table.'.'.$id_field.') * '.
424  round(50/sizeof($query_score)).' / '.
425  '(SELECT '.$count_field.' FROM '.$this->_count.' WHERE '.$this->_count.'.'.$id_field.'='.$relation.')';
426  if ($use_query_andorscore)
427  {
428  $query['score'][] = $score;
429  } else {
430  $query['fields2'] = '('.$score.') AS score';
431  }
432  if (!isset($query['order']))
433  {
434  $query['order'] = 'score DESC';
435  }
436  }
437  if ($score_select && $query_score)
438  {
439  $score = $score_select.' AND ('.join(' OR ',$query_score).') AND '.$relation.'='.$cond_field2;
440 
441  $query['score'] = array($score);
442 
443  if (!isset($query['order']))
444  {
445  $query['order'] = 'score DESC';
446  }
447  }
448  if ($this->extraQuery) {
449  if ($query['where']) {
450  $query['where'] .= " AND {$this->extraQuery}";
451  } else {
452  $query['where'] = $this->extraQuery;
453  }
454  }
455  return $query;
456  }
457 }
458 ?>
_getContent($page, $k)
Definition: Ego_Search.php:166
checkSearch($search)
Definition: Ego_Search.php:513
replace($part, $reverse=false)
update($index, $page, $count=array())
static $replace_source
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)
static getDbDriver()
__construct($table, $suffix='_fulltext')
static $replace_target