4 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
\r
5 * Copyright (C) 2003-2009 The Nucleus Group
\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
14 * SEARCH(querystring) offers different functionality to create an
\r
15 * SQL query to find certain items. (and comments)
\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
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
36 function SEARCH($text) {
\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
44 // get all public searchable blogs, no matter what, include the current blog allways.
\r
45 $res = sql_query('SELECT bnumber FROM '.sql_table('blog').' WHERE bincludesearch=1 ');
\r
46 while ($obj = sql_fetch_object($res))
\r
47 $this->blogs[] = intval($obj->bnumber);
\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=i18n::explode(" ",$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
58 $stringsum_a[] = ' '.$this->boolean_sql_select_short($result[$cth],$match).' ';
\r
62 if(i18n::strlen($stringsum_long)>0){
\r
63 $stringsum_long = sql_real_escape_string($stringsum_long);
\r
64 $stringsum_a[] = " match ($match) against ('$stringsum_long') ";
\r
67 $stringsum .= implode("+",$stringsum_a);
\r
72 function boolean_inclusive_atoms($string){
\r
73 $result = trim($string);
\r
74 $result = preg_replace("#([[:space:]]{2,})#", ' ', $result);
\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
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
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
90 /* strip exlusive atoms */
\r
91 $result = preg_replace(
\r
92 "#\-\([A-Za-z0-9]{1,}[A-Za-z0-9\-\.\_\,]{0,}\)#",
\r
96 $result = str_replace('(', ' ', $result);
\r
97 $result = str_replace(')', ' ', $result);
\r
98 $result = str_replace(',', ' ', $result);
\r
103 function boolean_sql_where($match){
\r
105 $result = $this->marked;
\r
107 $this->boolean_sql_where_cb1($match); // set the static $match
\r
109 $result = preg_replace_callback(
\r
111 "/foo\[\(\'([^\)]{4,})\'\)\]bar/",
\r
113 array($this,'boolean_sql_where_cb1'),
\r
117 $this->boolean_sql_where_cb2($match); // set the static $match
\r
119 $result = preg_replace_callback(
\r
121 "/foo\[\(\'([^\)]{1,3})\'\)\]bar/",
\r
123 array($this,'boolean_sql_where_cb2'),
\r
131 function boolean_sql_where_cb1($matches){
\r
135 if (!is_array($matches)) $match=$matches;
\r
137 else return ' match ('.$match.') against (\''.sql_real_escape_string($matches[1]).'\') > 0 ';
\r
141 function boolean_sql_where_cb2($matches){
\r
145 if (!is_array($matches)) $match=$matches;
\r
147 else return ' ('.$this->boolean_sql_where_short(sql_real_escape_string($matches[1]),$match).') ';
\r
151 function boolean_mark_atoms($string){
\r
152 $result = trim($string);
\r
153 $result = preg_replace("/([[:space:]]{2,})/",' ',$result);
\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
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
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
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
175 /* apply arbitrary function to all 'word' atoms */
\r
177 $result_a = i18n::explode(' ', $result);
\r
179 for($word = 0;$word<count($result_a);$word++)
\r
181 $result_a[$word] = "foo[('" . $result_a[$word] . "')]bar";
\r
184 $result = implode(' ', $result_a);
\r
186 /* dispatch ' ' to ' AND ' */
\r
187 $result = str_replace(' ', ' AND ', $result);
\r
189 /* dispatch ',' to ' OR ' */
\r
190 $result = str_replace(',', ' OR ', $result);
\r
192 /* dispatch '-' to ' NOT ' */
\r
193 $result = str_replace(' -', ' NOT ', $result);
\r
197 function boolean_sql_where_short($string,$match){
\r
198 $match_a = i18n::explode(',',$match);
\r
199 for($ith=0;$ith<count($match_a);$ith++){
\r
200 $like_a[$ith] = " $match_a[$ith] LIKE '% $string %' ";
\r
202 $like = implode(" OR ",$like_a);
\r
206 function boolean_sql_select_short($string,$match){
\r
207 $match_a = i18n::explode(',',$match);
\r
208 $score_unit_weight = .2;
\r
209 for($ith=0;$ith<count($match_a);$ith++){
\r
211 " $score_unit_weight*(
\r
212 LENGTH(" . sql_real_escape_string($match_a[$ith]) . ") -
\r
213 LENGTH(REPLACE(LOWER(" . sql_real_escape_string($match_a[$ith]) . "),LOWER('" . sql_real_escape_string($string) . "'),'')))
\r
214 /LENGTH('" . sql_real_escape_string($string) . "') ";
\r
216 $score = implode(" + ",$score_a);
\r