OSDN Git Service

[NEW] データベースをハンドルする新しいDBクラスを追加。関連する修正を反映。
[nucleus-jp/nucleus-next.git] / nucleus / libs / SEARCH.php
1 <?php\r
2 \r
3 /*\r
4  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)\r
5  * Copyright (C) 2003-2009 The Nucleus Group\r
6  *\r
7  * This program is free software; you can redistribute it and/or\r
8  * modify it under the terms of the GNU General Public License\r
9  * as published by the Free Software Foundation; either version 2\r
10  * of the License, or (at your option) any later version.\r
11  * (see nucleus/documentation/index.html#license for more info)\r
12  */\r
13 /**\r
14  * SEARCH(querystring) offers different functionality to create an\r
15  * SQL query to find certain items. (and comments)\r
16  *\r
17  * based on code by David Altherr:\r
18  * http://www.evolt.org/article/Boolean_Fulltext_Searching_with_PHP_and_MySQL/18/15665/\r
19  * http://davidaltherr.net/web/php_functions/boolean/funcs.mysql.boolean.txt\r
20  *\r
21  * @license http://nucleuscms.org/license.txt GNU General Public License\r
22  * @copyright Copyright (C) 2002-2012 The Nucleus Group\r
23  * @version $Id: SEARCH.php 1556 2011-07-11 14:18:48Z ftruscot $\r
24  */\r
25 \r
26 \r
27 \r
28 class Search\r
29 {\r
30         var $querystring;\r
31         var $marked;\r
32         var $inclusive;\r
33         var $blogs;\r
34 \r
35 \r
36         function SEARCH($text) {\r
37                 global $blogid;\r
38                 $text = preg_replace ("/[<,>,=,?,!,#,^,(,),[,\],:,;,\\\,%]/","",$text);\r
39                 $this->querystring      = $text;\r
40                 $this->marked           = $this->boolean_mark_atoms($text);\r
41                 $this->inclusive        = $this->boolean_inclusive_atoms($text);\r
42                 $this->blogs            = array();\r
43 \r
44                 // get all public searchable blogs, no matter what, include the current blog allways.\r
45                 $res = DB::getResult('SELECT bnumber FROM '.sql_table('blog').' WHERE bincludesearch=1 ');\r
46                 foreach ( $res as $row )\r
47                         $this->blogs[] = intval($row['bnumber']);\r
48         }\r
49 \r
50         function  boolean_sql_select($match){\r
51                 if (i18n::strlen($this->inclusive) > 0) {\r
52                    /* build sql for determining score for each record */\r
53                    $result=preg_split("# #",$this->inclusive);\r
54                    for($cth=0;$cth<count($result);$cth++){\r
55                            if(i18n::strlen($result[$cth])>=4){\r
56                                    $stringsum_long .=  " $result[$cth] ";\r
57                            }else{\r
58                                    $stringsum_a[] = ' '.$this->boolean_sql_select_short($result[$cth],$match).' ';\r
59                            }\r
60                    }\r
61 \r
62                    if(i18n::strlen($stringsum_long)>0){\r
63                                 $stringsum_long = DB::quoteValue($stringsum_long);\r
64                                 $stringsum_a[] = " match ({$match}) against ({$stringsum_long}) ";\r
65                    }\r
66 \r
67                    $stringsum .= implode("+",$stringsum_a);\r
68                    return $stringsum;\r
69                 }\r
70         }\r
71 \r
72         function boolean_inclusive_atoms($string){\r
73                 $result = trim($string);\r
74                 $result = preg_replace("#([[:space:]]{2,})#", ' ', $result);\r
75 \r
76                 # replaced eregi_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0\r
77                 # just added delimiters to regex and the 'i' for case-insensitive matching\r
78 \r
79                 /* convert normal boolean operators to shortened syntax */\r
80                 $result = preg_replace('# not #i', ' -', $result);\r
81                 $result = preg_replace('# and #i', ' ', $result);\r
82                 $result = preg_replace('# or #i', ',', $result);\r
83 \r
84                 /* drop unnecessary spaces */\r
85                 $result = str_replace(' ,', ',', $result);\r
86                 $result = str_replace(', ', ',', $result);\r
87                 $result = str_replace('- ', '-', $result);\r
88                 $result = str_replace('+', '', $result);\r
89 \r
90                 /* strip exlusive atoms */\r
91                 $result = preg_replace(\r
92                         "#\-\([A-Za-z0-9]{1,}[A-Za-z0-9\-\.\_\,]{0,}\)#",\r
93                         '',\r
94                         $result);\r
95 \r
96                 $result = str_replace('(', ' ', $result);\r
97                 $result = str_replace(')', ' ', $result);\r
98                 $result = str_replace(',', ' ', $result);\r
99 \r
100                 return $result;\r
101         }\r
102 \r
103     function boolean_sql_where($match){\r
104 \r
105         $result = $this->marked;\r
106 \r
107         $this->boolean_sql_where_cb1($match); // set the static $match\r
108 \r
109         $result = preg_replace_callback(\r
110 \r
111             "/foo\[\(\'([^\)]{4,})\'\)\]bar/",\r
112 \r
113             array($this,'boolean_sql_where_cb1'),\r
114 \r
115             $result);\r
116 \r
117         $this->boolean_sql_where_cb2($match); // set the static $match\r
118 \r
119         $result = preg_replace_callback(\r
120 \r
121             "/foo\[\(\'([^\)]{1,3})\'\)\]bar/",\r
122 \r
123             array($this,'boolean_sql_where_cb2'),\r
124 \r
125             $result);\r
126 \r
127         return $result;\r
128 \r
129     }\r
130 \r
131     function boolean_sql_where_cb1($matches){\r
132 \r
133         static $match;\r
134 \r
135         if (!is_array($matches)) $match=$matches;\r
136 \r
137         else return ' match ('.$match.') against ('.DB::quoteValue($matches[1]).') > 0 ';\r
138 \r
139     }\r
140 \r
141     function boolean_sql_where_cb2($matches){\r
142 \r
143         static $match;\r
144 \r
145         if (!is_array($matches)) $match=$matches;\r
146 \r
147         else return ' ('.$this->boolean_sql_where_short($matches[1], $match).') ';\r
148 \r
149     }   \r
150 \r
151         function boolean_mark_atoms($string){\r
152                 $result = trim($string);\r
153                 $result = preg_replace("/([[:space:]]{2,})/",' ',$result);\r
154 \r
155                 # replaced eregi_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0\r
156                 # just added delimiters to regex and the 'i' for case-insensitive matching\r
157 \r
158                 /* convert normal boolean operators to shortened syntax */\r
159                 $result = preg_replace('# not #i', ' -', $result);\r
160                 $result = preg_replace('# and #i', ' ', $result);\r
161                 $result = preg_replace('# or #i', ',', $result);\r
162 \r
163                 /* strip excessive whitespace */\r
164                 $result = str_replace('( ', '(', $result);\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 \r
171                 // remove double spaces (we might have introduced some new ones above)\r
172                 $result = trim($result);\r
173                 $result = preg_replace("#([[:space:]]{2,})#", ' ', $result);\r
174 \r
175                 /* apply arbitrary function to all 'word' atoms */\r
176 \r
177                 $result_a = preg_split('# #', $result);\r
178 \r
179                 for($word = 0;$word<count($result_a);$word++)\r
180                 {\r
181                         $result_a[$word] = "foo[('" . $result_a[$word] . "')]bar";\r
182                 }\r
183 \r
184                 $result = implode(' ', $result_a);\r
185 \r
186                 /* dispatch ' ' to ' AND ' */\r
187                 $result = str_replace(' ', ' AND ', $result);\r
188 \r
189                 /* dispatch ',' to ' OR ' */\r
190                 $result = str_replace(',', ' OR ', $result);\r
191 \r
192                 /* dispatch '-' to ' NOT ' */\r
193                 $result = str_replace(' -', ' NOT ', $result);\r
194                 return $result;\r
195         }\r
196 \r
197         function boolean_sql_where_short($string,$match){\r
198                 $match_a = preg_split('#,#',$match);\r
199                 for($ith=0;$ith<count($match_a);$ith++){\r
200                         $like_a[$ith] = ' $match_a[$ith] LIKE ' . DB::quoteValue("% {$string} %") . ' ';\r
201                 }\r
202                 $like = implode(" OR ",$like_a);\r
203 \r
204                 return $like;\r
205         }\r
206         function boolean_sql_select_short($string,$match){\r
207                 $match_a = preg_split('#,#',$match);\r
208                 $score_unit_weight = .2;\r
209                 for($ith=0;$ith<count($match_a);$ith++){\r
210                         $score_a[$ith] =\r
211                                                    " $score_unit_weight*(\r
212                                                    LENGTH(" . DB::quoteValue($match_a[$ith]) . ") -\r
213                                                    LENGTH(REPLACE(LOWER(" . DB::quoteValue($match_a[$ith]) . "),LOWER(" . DB::quoteValue($string) . "),'')))\r
214                                                    /LENGTH(" . DB::quoteValue($string) . ") ";\r
215                 }\r
216                 $score = implode(" + ",$score_a);\r
217 \r
218                 return $score;\r
219         }\r
220 }\r
221 ?>\r