MediaWiki  1.23.14
SearchSqlite.php
Go to the documentation of this file.
1 <?php
34  return $this->db->checkForEnabledSearch();
35  }
36 
43  function parseQuery( $filteredText, $fulltext ) {
45  $lc = SearchEngine::legalSearchChars(); // Minus format chars
46  $searchon = '';
47  $this->searchTerms = array();
48 
49  $m = array();
50  if ( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
51  $filteredText, $m, PREG_SET_ORDER ) ) {
52  foreach ( $m as $bits ) {
53  @list( /* all */, $modifier, $term, $nonQuoted, $wildcard ) = $bits;
54 
55  if ( $nonQuoted != '' ) {
56  $term = $nonQuoted;
57  $quote = '';
58  } else {
59  $term = str_replace( '"', '', $term );
60  $quote = '"';
61  }
62 
63  if ( $searchon !== '' ) {
64  $searchon .= ' ';
65  }
66 
67  // Some languages such as Serbian store the input form in the search index,
68  // so we may need to search for matches in multiple writing system variants.
69  $convertedVariants = $wgContLang->autoConvertToAllVariants( $term );
70  if ( is_array( $convertedVariants ) ) {
71  $variants = array_unique( array_values( $convertedVariants ) );
72  } else {
73  $variants = array( $term );
74  }
75 
76  // The low-level search index does some processing on input to work
77  // around problems with minimum lengths and encoding in MySQL's
78  // fulltext engine.
79  // For Chinese this also inserts spaces between adjacent Han characters.
80  $strippedVariants = array_map(
81  array( $wgContLang, 'normalizeForSearch' ),
82  $variants );
83 
84  // Some languages such as Chinese force all variants to a canonical
85  // form when stripping to the low-level search index, so to be sure
86  // let's check our variants list for unique items after stripping.
87  $strippedVariants = array_unique( $strippedVariants );
88 
89  $searchon .= $modifier;
90  if ( count( $strippedVariants ) > 1 ) {
91  $searchon .= '(';
92  }
93  foreach ( $strippedVariants as $stripped ) {
94  if ( $nonQuoted && strpos( $stripped, ' ' ) !== false ) {
95  // Hack for Chinese: we need to toss in quotes for
96  // multiple-character phrases since normalizeForSearch()
97  // added spaces between them to make word breaks.
98  $stripped = '"' . trim( $stripped ) . '"';
99  }
100  $searchon .= "$quote$stripped$quote$wildcard ";
101  }
102  if ( count( $strippedVariants ) > 1 ) {
103  $searchon .= ')';
104  }
105 
106  // Match individual terms or quoted phrase in result highlighting...
107  // Note that variants will be introduced in a later stage for highlighting!
108  $regexp = $this->regexTerm( $term, $wildcard );
109  $this->searchTerms[] = $regexp;
110  }
111 
112  } else {
113  wfDebug( __METHOD__ . ": Can't understand search query '{$filteredText}'\n" );
114  }
115 
116  $searchon = $this->db->strencode( $searchon );
117  $field = $this->getIndexField( $fulltext );
118  return " $field MATCH '$searchon' ";
119  }
120 
121  function regexTerm( $string, $wildcard ) {
123 
124  $regex = preg_quote( $string, '/' );
125  if ( $wgContLang->hasWordBreaks() ) {
126  if ( $wildcard ) {
127  // Don't cut off the final bit!
128  $regex = "\b$regex";
129  } else {
130  $regex = "\b$regex\b";
131  }
132  } else {
133  // For Chinese, words may legitimately abut other words in the text literal.
134  // Don't add \b boundary checks... note this could cause false positives
135  // for latin chars.
136  }
137  return $regex;
138  }
139 
140  public static function legalSearchChars() {
141  return "\"*" . parent::legalSearchChars();
142  }
143 
150  function searchText( $term ) {
151  return $this->searchInternal( $term, true );
152  }
153 
160  function searchTitle( $term ) {
161  return $this->searchInternal( $term, false );
162  }
163 
164  protected function searchInternal( $term, $fulltext ) {
165  global $wgCountTotalSearchHits, $wgContLang;
166 
167  if ( !$this->fulltextSearchSupported() ) {
168  return null;
169  }
170 
171  $filteredTerm = $this->filter( $wgContLang->lc( $term ) );
172  $resultSet = $this->db->query( $this->getQuery( $filteredTerm, $fulltext ) );
173 
174  $total = null;
175  if ( $wgCountTotalSearchHits ) {
176  $totalResult = $this->db->query( $this->getCountQuery( $filteredTerm, $fulltext ) );
177  $row = $totalResult->fetchObject();
178  if ( $row ) {
179  $total = intval( $row->c );
180  }
181  $totalResult->free();
182  }
183 
184  return new SqliteSearchResultSet( $resultSet, $this->searchTerms, $total );
185  }
186 
191  function queryNamespaces() {
192  if ( is_null( $this->namespaces ) ) {
193  return ''; # search all
194  }
195  if ( !count( $this->namespaces ) ) {
196  $namespaces = '0';
197  } else {
198  $namespaces = $this->db->makeList( $this->namespaces );
199  }
200  return 'AND page_namespace IN (' . $namespaces . ')';
201  }
202 
208  function limitResult( $sql ) {
209  return $this->db->limitResult( $sql, $this->limit, $this->offset );
210  }
211 
219  function getQuery( $filteredTerm, $fulltext ) {
220  return $this->limitResult(
221  $this->queryMain( $filteredTerm, $fulltext ) . ' ' .
222  $this->queryNamespaces()
223  );
224  }
225 
231  function getIndexField( $fulltext ) {
232  return $fulltext ? 'si_text' : 'si_title';
233  }
234 
242  function queryMain( $filteredTerm, $fulltext ) {
243  $match = $this->parseQuery( $filteredTerm, $fulltext );
244  $page = $this->db->tableName( 'page' );
245  $searchindex = $this->db->tableName( 'searchindex' );
246  return "SELECT $searchindex.rowid, page_namespace, page_title " .
247  "FROM $page,$searchindex " .
248  "WHERE page_id=$searchindex.rowid AND $match";
249  }
250 
251  function getCountQuery( $filteredTerm, $fulltext ) {
252  $match = $this->parseQuery( $filteredTerm, $fulltext );
253  $page = $this->db->tableName( 'page' );
254  $searchindex = $this->db->tableName( 'searchindex' );
255  return "SELECT COUNT(*) AS c " .
256  "FROM $page,$searchindex " .
257  "WHERE page_id=$searchindex.rowid AND $match " .
258  $this->queryNamespaces();
259  }
260 
269  function update( $id, $title, $text ) {
270  if ( !$this->fulltextSearchSupported() ) {
271  return;
272  }
273  // @todo find a method to do it in a single request,
274  // couldn't do it so far due to typelessness of FTS3 tables.
275  $dbw = wfGetDB( DB_MASTER );
276 
277  $dbw->delete( 'searchindex', array( 'rowid' => $id ), __METHOD__ );
278 
279  $dbw->insert( 'searchindex',
280  array(
281  'rowid' => $id,
282  'si_title' => $title,
283  'si_text' => $text
284  ), __METHOD__ );
285  }
286 
294  function updateTitle( $id, $title ) {
295  if ( !$this->fulltextSearchSupported() ) {
296  return;
297  }
298  $dbw = wfGetDB( DB_MASTER );
299 
300  $dbw->update( 'searchindex',
301  array( 'si_title' => $title ),
302  array( 'rowid' => $id ),
303  __METHOD__ );
304  }
305 }
306 
311  function __construct( $resultSet, $terms, $totalHits = null ) {
312  parent::__construct( $resultSet, $terms );
313  $this->mTotalHits = $totalHits;
314  }
315 
316  function getTotalHits() {
317  return $this->mTotalHits;
318  }
319 }
SqliteSearchResultSet\__construct
__construct( $resultSet, $terms, $totalHits=null)
Definition: SearchSqlite.php:311
DB_MASTER
const DB_MASTER
Definition: Defines.php:56
php
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
Definition: skin.txt:62
SearchSqlite\searchTitle
searchTitle( $term)
Perform a title-only search query and return a result set.
Definition: SearchSqlite.php:160
wfGetDB
& wfGetDB( $db, $groups=array(), $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:3714
SearchSqlite\searchText
searchText( $term)
Perform a full text search query and return a result set.
Definition: SearchSqlite.php:150
SearchSqlite\limitResult
limitResult( $sql)
Returns a query with limit for number of results set.
Definition: SearchSqlite.php:208
SearchSqlite\legalSearchChars
static legalSearchChars()
Definition: SearchSqlite.php:140
$wgContLang
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the content language as $wgContLang
Definition: design.txt:56
SearchSqlite\fulltextSearchSupported
fulltextSearchSupported()
Whether fulltext search is supported by current schema.
Definition: SearchSqlite.php:33
SearchSqlite\queryMain
queryMain( $filteredTerm, $fulltext)
Get the base part of the search query.
Definition: SearchSqlite.php:242
SearchDatabase
Base search engine base class for database-backed searches.
Definition: SearchDatabase.php:29
namespaces
to move a page</td >< td > &*You are moving the page across namespaces
Definition: All_system_messages.txt:2677
$total
$total
Definition: Utf8Test.php:92
SearchSqlite\regexTerm
regexTerm( $string, $wildcard)
Definition: SearchSqlite.php:121
SqliteSearchResultSet\getTotalHits
getTotalHits()
Some search modes return a total hit count for the query in the entire article database.
Definition: SearchSqlite.php:316
SearchSqlite\getCountQuery
getCountQuery( $filteredTerm, $fulltext)
Definition: SearchSqlite.php:251
SearchSqlite\queryNamespaces
queryNamespaces()
Return a partial WHERE clause to limit the search to the given namespaces.
Definition: SearchSqlite.php:191
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
SearchEngine\filter
filter( $text)
Return a 'cleaned up' search string.
Definition: SearchEngine.php:435
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
$regexp
$regexp
Definition: mwdoc-filter.php:19
list
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
wfDebug
wfDebug( $text, $dest='all')
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:980
$title
presenting them properly to the user as errors is done by the caller $title
Definition: hooks.txt:1324
SqlSearchResultSet
This class is used for different SQL-based search engines shipped with MediaWiki.
Definition: SearchResultSet.php:140
SearchSqlite\getIndexField
getIndexField( $fulltext)
Picks which field to index on, depending on what type of query.
Definition: SearchSqlite.php:231
SqliteSearchResultSet
Definition: SearchSqlite.php:310
SearchEngine\legalSearchChars
static legalSearchChars()
Definition: SearchEngine.php:256
SearchEngine\$namespaces
$namespaces
Definition: SearchEngine.php:37
SearchSqlite
Search engine hook for SQLite.
Definition: SearchSqlite.php:28
SearchSqlite\getQuery
getQuery( $filteredTerm, $fulltext)
Construct the full SQL query to do the search.
Definition: SearchSqlite.php:219
$term
the value to return A Title object or null whereas SearchGetNearMatch runs after $term
Definition: hooks.txt:2136
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
SearchSqlite\update
update( $id, $title, $text)
Create or update the search index record for the given page.
Definition: SearchSqlite.php:269
SearchSqlite\updateTitle
updateTitle( $id, $title)
Update a search index record's title only.
Definition: SearchSqlite.php:294
SearchSqlite\parseQuery
parseQuery( $filteredText, $fulltext)
Parse the user's query and transform it into an SQL fragment which will become part of a WHERE clause...
Definition: SearchSqlite.php:43
SearchSqlite\searchInternal
searchInternal( $term, $fulltext)
Definition: SearchSqlite.php:164