Reorganization of SearchEngine for legibility
[lhc/web/wiklou.git] / includes / SearchEngine.php
1 <?php
2
3 class SearchEngine {
4 var $limit = 10;
5 var $offset = 0;
6 var $searchTerms = array();
7 var $namespaces = array( 0 );
8 var $showRedirects = false;
9
10 /**
11 * Perform a full text search query and return a result set.
12 *
13 * @param string $term - Raw search term
14 * @param array $namespaces - List of namespaces to search
15 * @return ResultWrapper
16 * @access public
17 */
18 function searchText( $term ) {
19 return $this->db->resultObject( $this->db->query( $this->getQuery( $this->filter( $term ), true ) ) );
20 }
21
22 /**
23 * Perform a title-only search query and return a result set.
24 *
25 * @param string $term - Raw search term
26 * @param array $namespaces - List of namespaces to search
27 * @return ResultWrapper
28 * @access public
29 */
30 function searchTitle( $term ) {
31 return $this->db->resultObject( $this->db->query( $this->getQuery( $this->filter( $term ), false ) ) );
32 }
33
34 /**
35 * If an exact title match can be find, or a very slightly close match,
36 * return the title. If no match, returns NULL.
37 *
38 * @param string $term
39 * @return Title
40 * @access private
41 */
42 function getNearMatch( $term ) {
43 # Exact match? No need to look further.
44 $title = Title::newFromText( $term );
45 if ( $title->getNamespace() == NS_SPECIAL || 0 != $title->getArticleID() ) {
46 return $title;
47 }
48
49 # Now try all lower case (i.e. first letter capitalized)
50 #
51 $title = Title::newFromText( strtolower( $term ) );
52 if ( 0 != $title->getArticleID() ) {
53 return $title;
54 }
55
56 # Now try capitalized string
57 #
58 $title = Title::newFromText( ucwords( strtolower( $term ) ) );
59 if ( 0 != $title->getArticleID() ) {
60 return $title;
61 }
62
63 # Now try all upper case
64 #
65 $title = Title::newFromText( strtoupper( $term ) );
66 if ( 0 != $title->getArticleID() ) {
67 return $title;
68 }
69
70 # Entering an IP address goes to the contributions page
71 if ( preg_match( '/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $term ) ) {
72 $title = Title::makeTitle( NS_SPECIAL, "Contributions/" . $term );
73 return $title;
74 }
75
76 return NULL;
77 }
78
79 function legalSearchChars() {
80 return "A-Za-z_'0-9\\x80-\\xFF\\-";
81 }
82
83 /**
84 * Set the maximum number of results to return
85 * and how many to skip before returning the first.
86 *
87 * @param int $limit
88 * @param int $offset
89 * @access public
90 */
91 function setLimitOffset( $limit, $offset = 0 ) {
92 $this->limit = IntVal( $limit );
93 $this->offset = IntVal( $offset );
94 }
95
96 /**
97 * Set which namespaces the search should include.
98 * Give an array of namespace index numbers.
99 *
100 * @param array $namespaces
101 * @access public
102 */
103 function setNamespaces( $namespaces ) {
104 $this->namespaces = $namespaces;
105 }
106
107 /**
108 * Make a list of searchable namespaces and their canonical names.
109 * @return array
110 * @access public
111 */
112 function searchableNamespaces() {
113 global $wgContLang;
114 $arr = array();
115 foreach( $wgContLang->getNamespaces() as $ns => $name ) {
116 if( $ns >= 0 ) {
117 $arr[$ns] = $name;
118 }
119 }
120 return $arr;
121 }
122
123 /**
124 * Fetch an array of regular expression fragments for matching
125 * the search terms as parsed by this engine in a text extract.
126 *
127 * @return array
128 * @access public
129 */
130 function termMatches() {
131 return $this->searchTerms;
132 }
133
134 /**
135 * Return a 'cleaned up' search string
136 *
137 * @return string
138 * @access public
139 */
140 function filter( $text ) {
141 $lc = $this->legalSearchChars();
142 return trim( preg_replace( "/[^{$lc}]/", " ", $text ) );
143 }
144
145 /**
146 * Return a partial WHERE clause to exclude redirects, if so set
147 * @return string
148 * @access private
149 */
150 function queryRedirect() {
151 if( $this->showRedirects ) {
152 return 'AND cur_is_redirect=0';
153 } else {
154 return '';
155 }
156 }
157
158 /**
159 * Return a partial WHERE clause to limit the search to the given namespaces
160 * @return string
161 * @access private
162 */
163 function queryNamespaces() {
164 $namespaces = implode( ',', $this->namespaces );
165 if ($namespaces == '') {
166 $namespaces = '0';
167 }
168 return 'AND cur_namespace IN (' . $namespaces . ')';
169 }
170
171 /**
172 * Return a LIMIT clause to limit results on the query.
173 * @return string
174 * @access private
175 */
176 function queryLimit() {
177 return $this->db->limitResult( $this->limit, $this->offset );
178 }
179
180 /**
181 * Construct the full SQL query to do the search.
182 * The guts shoulds be constructed in queryMain()
183 * @param string $filteredTerm
184 * @param bool $fulltext
185 * @access private
186 */
187 function getQuery( $filteredTerm, $fulltext ) {
188 return $this->queryMain( $filteredTerm, $fulltext ) . ' ' .
189 $this->queryRedirect() . ' ' .
190 $this->queryNamespaces() . ' ' .
191 $this->queryLimit();
192 }
193
194 }
195
196 class SearchEngineDummy {
197 function search( $term ) {
198 return null;
199 }
200 }
201
202
203 ?>