3 * Contain a class for special pages
13 var $searchTerms = array();
14 var $namespaces = array( 0 );
15 var $showRedirects = false;
18 * Perform a full text search query and return a result set.
20 * @param string $term - Raw search term
21 * @param array $namespaces - List of namespaces to search
22 * @return ResultWrapper
25 function searchText( $term ) {
26 return $this->db
->resultObject( $this->db
->query( $this->getQuery( $this->filter( $term ), true ) ) );
30 * Perform a title-only search query and return a result set.
32 * @param string $term - Raw search term
33 * @param array $namespaces - List of namespaces to search
34 * @return ResultWrapper
37 function searchTitle( $term ) {
38 return $this->db
->resultObject( $this->db
->query( $this->getQuery( $this->filter( $term ), false ) ) );
42 * If an exact title match can be find, or a very slightly close match,
43 * return the title. If no match, returns NULL.
50 function getNearMatch( $term ) {
51 # Exact match? No need to look further.
52 $title = Title
::newFromText( $term );
53 if ( $title->getNamespace() == NS_SPECIAL ||
0 != $title->getArticleID() ) {
57 # Now try all lower case (i.e. first letter capitalized)
59 $title = Title
::newFromText( strtolower( $term ) );
60 if ( 0 != $title->getArticleID() ) {
64 # Now try capitalized string
66 $title = Title
::newFromText( ucwords( strtolower( $term ) ) );
67 if ( 0 != $title->getArticleID() ) {
71 # Now try all upper case
73 $title = Title
::newFromText( strtoupper( $term ) );
74 if ( 0 != $title->getArticleID() ) {
78 $title = Title
::newFromText( $term );
80 # Entering an IP address goes to the contributions page
81 if ( ( $title->getNamespace() == NS_USER
&& User
::isIP($title->getText() ) )
82 || User
::isIP( trim( $term ) ) ) {
83 return Title
::makeTitle( NS_SPECIAL
, "Contributions/" . $title->getDbkey() );
87 # Entering a user goes to the user page whether it's there or not
88 if ( $title->getNamespace() == NS_USER
) {
92 # Quoted term? Try without the quotes...
93 if( preg_match( '/^"([^"]+)"$/', $term, $matches ) ) {
94 return SearchEngine
::getNearMatch( $matches[1] );
100 function legalSearchChars() {
101 return "A-Za-z_'0-9\\x80-\\xFF\\-";
105 * Set the maximum number of results to return
106 * and how many to skip before returning the first.
112 function setLimitOffset( $limit, $offset = 0 ) {
113 $this->limit
= IntVal( $limit );
114 $this->offset
= IntVal( $offset );
118 * Set which namespaces the search should include.
119 * Give an array of namespace index numbers.
121 * @param array $namespaces
124 function setNamespaces( $namespaces ) {
125 $this->namespaces
= $namespaces;
129 * Make a list of searchable namespaces and their canonical names.
133 function searchableNamespaces() {
136 foreach( $wgContLang->getNamespaces() as $ns => $name ) {
137 if( $ns >= NS_MAIN
) {
145 * Fetch an array of regular expression fragments for matching
146 * the search terms as parsed by this engine in a text extract.
151 function termMatches() {
152 return $this->searchTerms
;
156 * Return a 'cleaned up' search string
161 function filter( $text ) {
162 $lc = $this->legalSearchChars();
163 return trim( preg_replace( "/[^{$lc}]/", " ", $text ) );
167 * Return a partial WHERE clause to exclude redirects, if so set
171 function queryRedirect() {
172 if( $this->showRedirects
) {
173 return 'AND cur_is_redirect=0';
180 * Return a partial WHERE clause to limit the search to the given namespaces
184 function queryNamespaces() {
185 $namespaces = implode( ',', $this->namespaces
);
186 if ($namespaces == '') {
189 return 'AND page_namespace IN (' . $namespaces . ')';
193 * Return a LIMIT clause to limit results on the query.
197 function queryLimit() {
198 return $this->db
->limitResult( $this->limit
, $this->offset
);
202 * Does not do anything for generic search engine
203 * subclasses may define this though
207 function queryRanking($filteredTerm,$fulltext) {
212 * Construct the full SQL query to do the search.
213 * The guts shoulds be constructed in queryMain()
214 * @param string $filteredTerm
215 * @param bool $fulltext
218 function getQuery( $filteredTerm, $fulltext ) {
219 return $this->queryMain( $filteredTerm, $fulltext ) . ' ' .
220 $this->queryRedirect() . ' ' .
221 $this->queryNamespaces() . ' ' .
222 $this->queryRanking($filteredTerm, $fulltext) . ' ' .
227 * Load up the appropriate search engine class for the currently
228 * active database backend, and return a configured instance.
230 * @return SearchEngine
234 global $wgDBtype, $wgDBmysql4, $wgSearchType;
235 if( $wgDBtype == 'mysql' ) {
237 $class = 'SearchMySQL4';
238 require_once( 'SearchMySQL4.php' );
240 $class = 'SearchMysql3';
241 require_once( 'SearchMySQL3.php' );
243 } else if ( $wgDBtype == 'PostgreSQL' ) {
244 $class = 'SearchTsearch2';
245 require_once( 'SearchTsearch2.php' );
247 $class = 'SearchEngineDummy';
249 $search = new $class( wfGetDB( DB_SLAVE
) );
250 $search->setLimitOffset(0,0);
260 class SearchEngineDummy
{
261 function search( $term ) {