OSDN Git Service

Merge branch 'skinnable-master'
[nucleus-jp/nucleus-next.git] / nucleus / libs / SEARCH.php
1 <<<<<<< HEAD
2 <?php\r
3 \r
4 /*\r
5  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)\r
6  * Copyright (C) 2003-2009 The Nucleus Group\r
7  *\r
8  * This program is free software; you can redistribute it and/or\r
9  * modify it under the terms of the GNU General Public License\r
10  * as published by the Free Software Foundation; either version 2\r
11  * of the License, or (at your option) any later version.\r
12  * (see nucleus/documentation/index.html#license for more info)\r
13  */\r
14 /**\r
15  * SEARCH(querystring) offers different functionality to create an\r
16  * SQL query to find certain items. (and comments)\r
17  *\r
18  * based on code by David Altherr:\r
19  * http://www.evolt.org/article/Boolean_Fulltext_Searching_with_PHP_and_MySQL/18/15665/\r
20  * http://davidaltherr.net/web/php_functions/boolean/funcs.mysql.boolean.txt\r
21  *\r
22  * @license http://nucleuscms.org/license.txt GNU General Public License\r
23  * @copyright Copyright (C) 2002-2012 The Nucleus Group\r
24  * @version $Id: SEARCH.php 1556 2011-07-11 14:18:48Z ftruscot $\r
25  */\r
26 \r
27 \r
28 \r
29 class Search\r
30 {\r
31         var $querystring;\r
32         var $marked;\r
33         var $inclusive;\r
34         var $blogs;\r
35 \r
36 \r
37         function SEARCH($text) {\r
38                 global $blogid;\r
39                 $text = preg_replace ("/[<,>,=,?,!,#,^,(,),[,\],:,;,\\\,%]/","",$text);\r
40                 $this->querystring      = $text;\r
41                 $this->marked           = $this->boolean_mark_atoms($text);\r
42                 $this->inclusive        = $this->boolean_inclusive_atoms($text);\r
43                 $this->blogs            = array();\r
44 \r
45                 // get all public searchable blogs, no matter what, include the current blog allways.\r
46                 $res = DB::getResult('SELECT bnumber FROM '.sql_table('blog').' WHERE bincludesearch=1 ');\r
47                 foreach ( $res as $row )\r
48                         $this->blogs[] = intval($row['bnumber']);\r
49         }\r
50 \r
51         function  boolean_sql_select($match){\r
52                 if (i18n::strlen($this->inclusive) > 0) {\r
53                    /* build sql for determining score for each record */\r
54                    $result=preg_split("# #",$this->inclusive);\r
55                    for($cth=0;$cth<count($result);$cth++){\r
56                            if(i18n::strlen($result[$cth])>=4){\r
57                                    $stringsum_long .=  " $result[$cth] ";\r
58                            }else{\r
59                                    $stringsum_a[] = ' '.$this->boolean_sql_select_short($result[$cth],$match).' ';\r
60                            }\r
61                    }\r
62 \r
63                    if(i18n::strlen($stringsum_long)>0){\r
64                                 $stringsum_long = DB::quoteValue($stringsum_long);\r
65                                 $stringsum_a[] = " match ({$match}) against ({$stringsum_long}) ";\r
66                    }\r
67 \r
68                    $stringsum .= implode("+",$stringsum_a);\r
69                    return $stringsum;\r
70                 }\r
71         }\r
72 \r
73         function boolean_inclusive_atoms($string){\r
74                 $result = trim($string);\r
75                 $result = preg_replace("#([[:space:]]{2,})#", ' ', $result);\r
76 \r
77                 # replaced eregi_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0\r
78                 # just added delimiters to regex and the 'i' for case-insensitive matching\r
79 \r
80                 /* convert normal boolean operators to shortened syntax */\r
81                 $result = preg_replace('# not #i', ' -', $result);\r
82                 $result = preg_replace('# and #i', ' ', $result);\r
83                 $result = preg_replace('# or #i', ',', $result);\r
84 \r
85                 /* drop unnecessary spaces */\r
86                 $result = str_replace(' ,', ',', $result);\r
87                 $result = str_replace(', ', ',', $result);\r
88                 $result = str_replace('- ', '-', $result);\r
89                 $result = str_replace('+', '', $result);\r
90 \r
91                 /* strip exlusive atoms */\r
92                 $result = preg_replace(\r
93                         "#\-\([A-Za-z0-9]{1,}[A-Za-z0-9\-\.\_\,]{0,}\)#",\r
94                         '',\r
95                         $result);\r
96 \r
97                 $result = str_replace('(', ' ', $result);\r
98                 $result = str_replace(')', ' ', $result);\r
99                 $result = str_replace(',', ' ', $result);\r
100 \r
101                 return $result;\r
102         }\r
103 \r
104     function boolean_sql_where($match){\r
105 \r
106         $result = $this->marked;\r
107 \r
108         $this->boolean_sql_where_cb1($match); // set the static $match\r
109 \r
110         $result = preg_replace_callback(\r
111 \r
112             "/foo\[\(\'([^\)]{4,})\'\)\]bar/",\r
113 \r
114             array($this,'boolean_sql_where_cb1'),\r
115 \r
116             $result);\r
117 \r
118         $this->boolean_sql_where_cb2($match); // set the static $match\r
119 \r
120         $result = preg_replace_callback(\r
121 \r
122             "/foo\[\(\'([^\)]{1,3})\'\)\]bar/",\r
123 \r
124             array($this,'boolean_sql_where_cb2'),\r
125 \r
126             $result);\r
127 \r
128         return $result;\r
129 \r
130     }\r
131 \r
132     function boolean_sql_where_cb1($matches){\r
133 \r
134         static $match;\r
135 \r
136         if (!is_array($matches)) $match=$matches;\r
137 \r
138         else return ' match ('.$match.') against ('.DB::quoteValue($matches[1]).') > 0 ';\r
139 \r
140     }\r
141 \r
142     function boolean_sql_where_cb2($matches){\r
143 \r
144         static $match;\r
145 \r
146         if (!is_array($matches)) $match=$matches;\r
147 \r
148         else return ' ('.$this->boolean_sql_where_short($matches[1], $match).') ';\r
149 \r
150     }   \r
151 \r
152         function boolean_mark_atoms($string){\r
153                 $result = trim($string);\r
154                 $result = preg_replace("/([[:space:]]{2,})/",' ',$result);\r
155 \r
156                 # replaced eregi_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0\r
157                 # just added delimiters to regex and the 'i' for case-insensitive matching\r
158 \r
159                 /* convert normal boolean operators to shortened syntax */\r
160                 $result = preg_replace('# not #i', ' -', $result);\r
161                 $result = preg_replace('# and #i', ' ', $result);\r
162                 $result = preg_replace('# or #i', ',', $result);\r
163 \r
164                 /* strip excessive whitespace */\r
165                 $result = str_replace('( ', '(', $result);\r
166                 $result = str_replace(' )', ')', $result);\r
167                 $result = str_replace(', ', ',', $result);\r
168                 $result = str_replace(' ,', ',', $result);\r
169                 $result = str_replace('- ', '-', $result);\r
170                 $result = str_replace('+', '', $result);\r
171 \r
172                 // remove double spaces (we might have introduced some new ones above)\r
173                 $result = trim($result);\r
174                 $result = preg_replace("#([[:space:]]{2,})#", ' ', $result);\r
175 \r
176                 /* apply arbitrary function to all 'word' atoms */\r
177 \r
178                 $result_a = preg_split('# #', $result);\r
179 \r
180                 for($word = 0;$word<count($result_a);$word++)\r
181                 {\r
182                         $result_a[$word] = "foo[('" . $result_a[$word] . "')]bar";\r
183                 }\r
184 \r
185                 $result = implode(' ', $result_a);\r
186 \r
187                 /* dispatch ' ' to ' AND ' */\r
188                 $result = str_replace(' ', ' AND ', $result);\r
189 \r
190                 /* dispatch ',' to ' OR ' */\r
191                 $result = str_replace(',', ' OR ', $result);\r
192 \r
193                 /* dispatch '-' to ' NOT ' */\r
194                 $result = str_replace(' -', ' NOT ', $result);\r
195                 return $result;\r
196         }\r
197 \r
198         function boolean_sql_where_short($string,$match){\r
199                 $match_a = preg_split('#,#',$match);\r
200                 for($ith=0;$ith<count($match_a);$ith++){\r
201                         $like_a[$ith] = ' $match_a[$ith] LIKE ' . DB::quoteValue("% {$string} %") . ' ';\r
202                 }\r
203                 $like = implode(" OR ",$like_a);\r
204 \r
205                 return $like;\r
206         }\r
207         function boolean_sql_select_short($string,$match){\r
208                 $match_a = preg_split('#,#',$match);\r
209                 $score_unit_weight = .2;\r
210                 for($ith=0;$ith<count($match_a);$ith++){\r
211                         $score_a[$ith] =\r
212                                                    " $score_unit_weight*(\r
213                                                    LENGTH(" . DB::quoteValue($match_a[$ith]) . ") -\r
214                                                    LENGTH(REPLACE(LOWER(" . DB::quoteValue($match_a[$ith]) . "),LOWER(" . DB::quoteValue($string) . "),'')))\r
215                                                    /LENGTH(" . DB::quoteValue($string) . ") ";\r
216                 }\r
217                 $score = implode(" + ",$score_a);\r
218 \r
219                 return $score;\r
220         }\r
221 }\r
222 ?>\r
223 =======
224 <?php
225
226 /*
227  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
228  * Copyright (C) 2003-2009 The Nucleus Group
229  *
230  * This program is free software; you can redistribute it and/or
231  * modify it under the terms of the GNU General Public License
232  * as published by the Free Software Foundation; either version 2
233  * of the License, or (at your option) any later version.
234  * (see nucleus/documentation/index.html#license for more info)
235  */
236 /**
237  * SEARCH(querystring) offers different functionality to create an
238  * SQL query to find certain items. (and comments)
239  *
240  * based on code by David Altherr:
241  * http://www.evolt.org/article/Boolean_Fulltext_Searching_with_PHP_and_MySQL/18/15665/
242  * http://davidaltherr.net/web/php_functions/boolean/funcs.mysql.boolean.txt
243  *
244  * @license http://nucleuscms.org/license.txt GNU General Public License
245  * @copyright Copyright (C) 2002-2009 The Nucleus Group
246  * @version $Id: SEARCH.php 1886 2012-06-17 08:27:27Z sakamocchi $
247  */
248
249
250
251 class Search
252 {
253         var $querystring;
254         var $marked;
255         var $inclusive;
256         var $blogs;
257
258
259         function SEARCH($text) {
260                 global $blogid;
261                 $text = preg_replace ("/[<,>,=,?,!,#,^,(,),[,\],:,;,\\\,%]/","",$text);
262                 $this->querystring      = $text;
263                 $this->marked           = $this->boolean_mark_atoms($text);
264                 $this->inclusive        = $this->boolean_inclusive_atoms($text);
265                 $this->blogs            = array();
266
267                 // get all public searchable blogs, no matter what, include the current blog allways.
268                 $res = DB::getResult('SELECT bnumber FROM '.sql_table('blog').' WHERE bincludesearch=1 ');
269                 foreach ( $res as $row )
270                         $this->blogs[] = intval($row['bnumber']);
271         }
272
273         function  boolean_sql_select($match){
274                 if (i18n::strlen($this->inclusive) > 0) {
275                    /* build sql for determining score for each record */
276                    $result=preg_split("# #",$this->inclusive);
277                    for($cth=0;$cth<count($result);$cth++){
278                            if(i18n::strlen($result[$cth])>=4){
279                                    $stringsum_long .=  " $result[$cth] ";
280                            }else{
281                                    $stringsum_a[] = ' '.$this->boolean_sql_select_short($result[$cth],$match).' ';
282                            }
283                    }
284
285                    if(i18n::strlen($stringsum_long)>0){
286                                 $stringsum_long = DB::quoteValue($stringsum_long);
287                                 $stringsum_a[] = " match ({$match}) against ({$stringsum_long}) ";
288                    }
289
290                    $stringsum .= implode("+",$stringsum_a);
291                    return $stringsum;
292                 }
293         }
294
295         function boolean_inclusive_atoms($string){
296                 $result = trim($string);
297                 $result = preg_replace("#([[:space:]]{2,})#", ' ', $result);
298
299                 # replaced eregi_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0
300                 # just added delimiters to regex and the 'i' for case-insensitive matching
301
302                 /* convert normal boolean operators to shortened syntax */
303                 $result = preg_replace('# not #i', ' -', $result);
304                 $result = preg_replace('# and #i', ' ', $result);
305                 $result = preg_replace('# or #i', ',', $result);
306
307                 /* drop unnecessary spaces */
308                 $result = str_replace(' ,', ',', $result);
309                 $result = str_replace(', ', ',', $result);
310                 $result = str_replace('- ', '-', $result);
311                 $result = str_replace('+', '', $result);
312
313                 /* strip exlusive atoms */
314                 $result = preg_replace(
315                         "#\-\([A-Za-z0-9]{1,}[A-Za-z0-9\-\.\_\,]{0,}\)#",
316                         '',
317                         $result);
318
319                 $result = str_replace('(', ' ', $result);
320                 $result = str_replace(')', ' ', $result);
321                 $result = str_replace(',', ' ', $result);
322
323                 return $result;
324         }
325
326     function boolean_sql_where($match){
327
328         $result = $this->marked;
329
330         $this->boolean_sql_where_cb1($match); // set the static $match
331
332         $result = preg_replace_callback(
333
334             "/foo\[\(\'([^\)]{4,})\'\)\]bar/",
335
336             array($this,'boolean_sql_where_cb1'),
337
338             $result);
339
340         $this->boolean_sql_where_cb2($match); // set the static $match
341
342         $result = preg_replace_callback(
343
344             "/foo\[\(\'([^\)]{1,3})\'\)\]bar/",
345
346             array($this,'boolean_sql_where_cb2'),
347
348             $result);
349
350         return $result;
351
352     }
353
354     function boolean_sql_where_cb1($matches){
355
356         static $match;
357
358         if (!is_array($matches)) $match=$matches;
359
360         else return ' match ('.$match.') against ('.DB::quoteValue($matches[1]).') > 0 ';
361
362     }
363
364     function boolean_sql_where_cb2($matches){
365
366         static $match;
367
368         if (!is_array($matches)) $match=$matches;
369
370         else return ' ('.$this->boolean_sql_where_short($matches[1], $match).') ';
371
372     }   
373
374         function boolean_mark_atoms($string){
375                 $result = trim($string);
376                 $result = preg_replace("/([[:space:]]{2,})/",' ',$result);
377
378                 # replaced eregi_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0
379                 # just added delimiters to regex and the 'i' for case-insensitive matching
380
381                 /* convert normal boolean operators to shortened syntax */
382                 $result = preg_replace('# not #i', ' -', $result);
383                 $result = preg_replace('# and #i', ' ', $result);
384                 $result = preg_replace('# or #i', ',', $result);
385
386                 /* strip excessive whitespace */
387                 $result = str_replace('( ', '(', $result);
388                 $result = str_replace(' )', ')', $result);
389                 $result = str_replace(', ', ',', $result);
390                 $result = str_replace(' ,', ',', $result);
391                 $result = str_replace('- ', '-', $result);
392                 $result = str_replace('+', '', $result);
393
394                 // remove double spaces (we might have introduced some new ones above)
395                 $result = trim($result);
396                 $result = preg_replace("#([[:space:]]{2,})#", ' ', $result);
397
398                 /* apply arbitrary function to all 'word' atoms */
399
400                 $result_a = preg_split('# #', $result);
401
402                 for($word = 0;$word<count($result_a);$word++)
403                 {
404                         $result_a[$word] = "foo[('" . $result_a[$word] . "')]bar";
405                 }
406
407                 $result = implode(' ', $result_a);
408
409                 /* dispatch ' ' to ' AND ' */
410                 $result = str_replace(' ', ' AND ', $result);
411
412                 /* dispatch ',' to ' OR ' */
413                 $result = str_replace(',', ' OR ', $result);
414
415                 /* dispatch '-' to ' NOT ' */
416                 $result = str_replace(' -', ' NOT ', $result);
417                 return $result;
418         }
419
420         function boolean_sql_where_short($string,$match){
421                 $match_a = preg_split('#,#',$match);
422                 for($ith=0;$ith<count($match_a);$ith++){
423                         $like_a[$ith] = ' $match_a[$ith] LIKE ' . DB::quoteValue("% {$string} %") . ' ';
424                 }
425                 $like = implode(" OR ",$like_a);
426
427                 return $like;
428         }
429         function boolean_sql_select_short($string,$match){
430                 $match_a = preg_split('#,#',$match);
431                 $score_unit_weight = .2;
432                 for($ith=0;$ith<count($match_a);$ith++){
433                         $score_a[$ith] =
434                                                    " $score_unit_weight*(
435                                                    LENGTH(" . DB::quoteValue($match_a[$ith]) . ") -
436                                                    LENGTH(REPLACE(LOWER(" . DB::quoteValue($match_a[$ith]) . "),LOWER(" . DB::quoteValue($string) . "),'')))
437                                                    /LENGTH(" . DB::quoteValue($string) . ") ";
438                 }
439                 $score = implode(" + ",$score_a);
440
441                 return $score;
442         }
443 }
444 ?>
445 >>>>>>> skinnable-master