summaryrefslogtreecommitdiff
path: root/includes/search
diff options
context:
space:
mode:
authorLuke Shumaker <LukeShu@sbcglobal.net>2014-01-28 09:50:25 -0500
committerLuke Shumaker <LukeShu@sbcglobal.net>2014-01-28 09:50:25 -0500
commit5744df39e15f85c6cc8a9faf8924d77e76d2b216 (patch)
treea8c8dd40a94d1fa0d5377566aa5548ae55a163da /includes/search
parent4bb2aeca1d198391ca856aa16c40b8559c68daec (diff)
parent224b22a051051f6c2e494c3a2fb4adb42898e2d1 (diff)
Merge branch 'archwiki'
Conflicts: extensions/FluxBBAuthPlugin.php extensions/SyntaxHighlight_GeSHi/README extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.class.php extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.i18n.php extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.php extensions/SyntaxHighlight_GeSHi/geshi/docs/CHANGES extensions/SyntaxHighlight_GeSHi/geshi/docs/THANKS extensions/SyntaxHighlight_GeSHi/geshi/docs/TODO extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractClass.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractClass_logo.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractMethod.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractPrivateClass.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractPrivateClass_logo.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractPrivateMethod.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Class.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Class_logo.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Constant.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Constructor.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Destructor.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Function.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Global.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/I.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Index.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Interface.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Interface_logo.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/L.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Lminus.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Lplus.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Method.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Page.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Page_logo.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateClass.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateClass_logo.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateMethod.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateVariable.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/StaticMethod.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/StaticVariable.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/T.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Tminus.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Tplus.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Variable.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/blank.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/class_folder.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/file.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/folder.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/function_folder.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/next_button.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/next_button_disabled.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/package.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/package_folder.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/previous_button.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/previous_button_disabled.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/private_class_logo.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/tutorial.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/tutorial_folder.png extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/up_button.png extensions/SyntaxHighlight_GeSHi/geshi/docs/geshi-doc.html extensions/SyntaxHighlight_GeSHi/geshi/docs/geshi-doc.txt extensions/SyntaxHighlight_GeSHi/geshi/geshi.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/4cs.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/6502acme.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/6502kickass.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/6502tasm.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/68000devpac.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/abap.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/actionscript.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/actionscript3.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/ada.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/algol68.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/apache.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/applescript.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/apt_sources.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/asm.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/asp.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/autoconf.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/autohotkey.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/autoit.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/avisynth.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/awk.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/bascomavr.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/bash.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/basic4gl.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/bf.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/bibtex.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/blitzbasic.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/bnf.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/boo.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/c.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/c_loadrunner.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/c_mac.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/caddcl.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/cadlisp.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/cfdg.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/cfm.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/chaiscript.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/cil.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/clojure.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/cmake.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/cobol.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/coffeescript.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/cpp-qt.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/cpp.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/csharp.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/css.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/cuesheet.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/d.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/dcs.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/delphi.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/diff.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/div.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/dos.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/dot.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/e.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/ecmascript.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/eiffel.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/email.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/epc.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/erlang.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/euphoria.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/f1.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/falcon.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/fo.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/fortran.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/freebasic.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/fsharp.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/gambas.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/gdb.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/genero.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/genie.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/gettext.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/glsl.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/gml.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/gnuplot.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/go.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/groovy.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/gwbasic.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/haskell.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/hicest.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/hq9plus.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/html4strict.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/html5.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/icon.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/idl.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/ini.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/inno.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/intercal.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/io.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/j.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/java.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/java5.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/javascript.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/jquery.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/kixtart.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/klonec.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/klonecpp.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/latex.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/lb.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/lisp.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/llvm.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/locobasic.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/logtalk.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/lolcode.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/lotusformulas.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/lotusscript.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/lscript.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/lsl2.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/lua.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/m68k.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/magiksf.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/make.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/mapbasic.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/matlab.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/mirc.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/mmix.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/modula2.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/modula3.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/mpasm.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/mxml.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/mysql.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/newlisp.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/nsis.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/oberon2.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/objc.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/objeck.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/ocaml-brief.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/ocaml.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/oobas.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/oracle11.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/oracle8.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/oxygene.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/oz.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/pascal.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/pcre.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/per.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/perl.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/perl6.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/pf.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/php-brief.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/php.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/pic16.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/pike.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/pixelbender.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/pli.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/plsql.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/postgresql.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/povray.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/powerbuilder.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/powershell.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/proftpd.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/progress.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/prolog.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/properties.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/providex.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/purebasic.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/pycon.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/python.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/q.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/qbasic.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/rails.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/rebol.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/reg.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/robots.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/rpmspec.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/rsplus.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/ruby.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/sas.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/scala.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/scheme.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/scilab.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/sdlbasic.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/smalltalk.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/smarty.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/sql.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/systemverilog.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/tcl.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/teraterm.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/text.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/thinbasic.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/tsql.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/typoscript.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/unicon.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/uscript.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/vala.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/vb.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/vbnet.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/verilog.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/vhdl.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/vim.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/visualfoxpro.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/visualprolog.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/whitespace.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/whois.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/winbatch.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/xbasic.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/xml.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/xorg_conf.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/xpp.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/yaml.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/z80.php extensions/SyntaxHighlight_GeSHi/geshi/geshi/zxbasic.php
Diffstat (limited to 'includes/search')
-rw-r--r--includes/search/SearchEngine.php244
-rw-r--r--includes/search/SearchIBM_DB2.php234
-rw-r--r--includes/search/SearchMssql.php25
-rw-r--r--includes/search/SearchMySQL.php74
-rw-r--r--includes/search/SearchOracle.php170
-rw-r--r--includes/search/SearchPostgres.php83
-rw-r--r--includes/search/SearchSqlite.php52
-rw-r--r--includes/search/SearchUpdate.php132
8 files changed, 468 insertions, 546 deletions
diff --git a/includes/search/SearchEngine.php b/includes/search/SearchEngine.php
index 27a321ac..71c05d8b 100644
--- a/includes/search/SearchEngine.php
+++ b/includes/search/SearchEngine.php
@@ -45,7 +45,7 @@ class SearchEngine {
*/
protected $db;
- function __construct($db = null) {
+ function __construct( $db = null ) {
if ( $db ) {
$this->db = $db;
} else {
@@ -58,8 +58,8 @@ class SearchEngine {
* If title searches are not supported or disabled, return null.
* STUB
*
- * @param $term String: raw search term
- * @return SearchResultSet
+ * @param string $term raw search term
+ * @return SearchResultSet|Status|null
*/
function searchText( $term ) {
return null;
@@ -70,8 +70,8 @@ class SearchEngine {
* If title searches are not supported or disabled, return null.
* STUB
*
- * @param $term String: raw search term
- * @return SearchResultSet
+ * @param string $term raw search term
+ * @return SearchResultSet|null
*/
function searchTitle( $term ) {
return null;
@@ -93,8 +93,9 @@ class SearchEngine {
* @return Boolean
*/
public function supports( $feature ) {
- switch( $feature ) {
+ switch ( $feature ) {
case 'list-redirects':
+ case 'search-update':
return true;
case 'title-suffix-filter':
default:
@@ -118,7 +119,7 @@ class SearchEngine {
* on text to be used for searching or updating search index.
* Default implementation does nothing (simply returns $string).
*
- * @param $string string: String to process
+ * @param string $string String to process
* @return string
*/
public function normalizeText( $string ) {
@@ -163,7 +164,7 @@ class SearchEngine {
/**
* Really find the title match.
- * @return null|\Title
+ * @return null|Title
*/
private static function getNearMatchInternal( $searchterm ) {
global $wgContLang, $wgEnableSearchContributorsByIP;
@@ -183,10 +184,15 @@ class SearchEngine {
# Exact match? No need to look further.
$title = Title::newFromText( $term );
- if ( is_null( $title ) ){
+ if ( is_null( $title ) ) {
return null;
}
+ # Try files if searching in the Media: namespace
+ if ( $title->getNamespace() == NS_MEDIA ) {
+ $title = Title::makeTitle( NS_FILE, $title->getText() );
+ }
+
if ( $title->isSpecialPage() || $title->isExternal() || $title->exists() ) {
return $title;
}
@@ -197,22 +203,23 @@ class SearchEngine {
return $title;
}
+ if ( !wfRunHooks( 'SearchAfterNoDirectMatch', array( $term, &$title ) ) ) {
+ return $title;
+ }
+
# Now try all lower case (i.e. first letter capitalized)
- #
$title = Title::newFromText( $wgContLang->lc( $term ) );
if ( $title && $title->exists() ) {
return $title;
}
# Now try capitalized string
- #
$title = Title::newFromText( $wgContLang->ucwords( $term ) );
if ( $title && $title->exists() ) {
return $title;
}
# Now try all upper case
- #
$title = Title::newFromText( $wgContLang->uc( $term ) );
if ( $title && $title->exists() ) {
return $title;
@@ -233,7 +240,6 @@ class SearchEngine {
$title = Title::newFromText( $searchterm );
-
# Entering an IP address goes to the contributions page
if ( $wgEnableSearchContributorsByIP ) {
if ( ( $title->getNamespace() == NS_USER && User::isIP( $title->getText() ) )
@@ -242,7 +248,6 @@ class SearchEngine {
}
}
-
# Entering a user goes to the user page whether it's there or not
if ( $title->getNamespace() == NS_USER ) {
return $title;
@@ -327,8 +332,9 @@ class SearchEngine {
$parsed = substr( $query, strlen( $prefix ) + 1 );
}
}
- if ( trim( $parsed ) == '' )
+ if ( trim( $parsed ) == '' ) {
$parsed = $query; // prefix was the whole query
+ }
wfRunHooks( 'SearchEngineReplacePrefixesComplete', array( $this, $query, &$parsed ) );
@@ -416,8 +422,9 @@ class SearchEngine {
$formatted = array_map( array( $wgContLang, 'getFormattedNsText' ), $namespaces );
foreach ( $formatted as $key => $ns ) {
- if ( empty( $ns ) )
+ if ( empty( $ns ) ) {
$formatted[$key] = wfMessage( 'blanknamespace' )->text();
+ }
}
return $formatted;
}
@@ -447,23 +454,46 @@ class SearchEngine {
* Load up the appropriate search engine class for the currently
* active database backend, and return a configured instance.
*
+ * @param String $type Type of search backend, if not the default
* @return SearchEngine
*/
- public static function create() {
+ public static function create( $type = null ) {
global $wgSearchType;
$dbr = null;
- if ( $wgSearchType ) {
+
+ $alternatives = self::getSearchTypes();
+
+ if ( $type && in_array( $type, $alternatives ) ) {
+ $class = $type;
+ } elseif ( $wgSearchType !== null ) {
$class = $wgSearchType;
} else {
$dbr = wfGetDB( DB_SLAVE );
$class = $dbr->getSearchEngine();
}
+
$search = new $class( $dbr );
$search->setLimitOffset( 0, 0 );
return $search;
}
/**
+ * Return the search engines we support. If only $wgSearchType
+ * is set, it'll be an array of just that one item.
+ *
+ * @return array
+ */
+ public static function getSearchTypes() {
+ global $wgSearchType, $wgSearchTypeAlternatives;
+ static $alternatives = null;
+ if ( $alternatives === null ) {
+ $alternatives = $wgSearchTypeAlternatives ?: array();
+ array_unshift( $alternatives, $wgSearchType );
+ }
+ return $alternatives;
+ }
+
+ /**
* Create or update the search index record for the given page.
* Title and text should be pre-processed.
* STUB
@@ -489,6 +519,18 @@ class SearchEngine {
}
/**
+ * Delete an indexed page
+ * Title should be pre-processed.
+ * STUB
+ *
+ * @param Integer $id Page id that was deleted
+ * @param String $title Title of page that was deleted
+ */
+ function delete( $id, $title ) {
+ // no-op
+ }
+
+ /**
* Get OpenSearch suggestion template
*
* @return String
@@ -505,6 +547,31 @@ class SearchEngine {
return $wgCanonicalServer . wfScript( 'api' ) . '?action=opensearch&search={searchTerms}&namespace=' . $ns;
}
}
+
+ /**
+ * Get the raw text for updating the index from a content object
+ * Nicer search backends could possibly do something cooler than
+ * just returning raw text
+ *
+ * @todo This isn't ideal, we'd really like to have content-specific handling here
+ * @param Title $t Title we're indexing
+ * @param Content $c Content of the page to index
+ * @return string
+ */
+ public function getTextFromContent( Title $t, Content $c = null ) {
+ return $c ? $c->getTextForSearchIndex() : '';
+ }
+
+ /**
+ * If an implementation of SearchEngine handles all of its own text processing
+ * in getTextFromContent() and doesn't require SearchUpdate::updateText()'s
+ * rather silly handling, it should return true here instead.
+ *
+ * @return bool
+ */
+ public function textAlreadyUpdatedForIndex() {
+ return false;
+ }
}
/**
@@ -637,26 +704,30 @@ class SqlSearchResultSet extends SearchResultSet {
}
function numRows() {
- if ( $this->mResultSet === false )
+ if ( $this->mResultSet === false ) {
return false;
+ }
return $this->mResultSet->numRows();
}
function next() {
- if ( $this->mResultSet === false )
+ if ( $this->mResultSet === false ) {
return false;
+ }
$row = $this->mResultSet->fetchObject();
- if ( $row === false )
+ if ( $row === false ) {
return false;
+ }
return SearchResult::newFromRow( $row );
}
function free() {
- if ( $this->mResultSet === false )
+ if ( $this->mResultSet === false ) {
return false;
+ }
$this->mResultSet->free();
}
@@ -669,7 +740,6 @@ class SearchResultTooMany {
# # Some search engines may bail out if too many matches are found
}
-
/**
* @todo FIXME: This class is horribly factored. It would probably be better to
* have a useful base class to which you pass some standard information, then
@@ -747,8 +817,9 @@ class SearchResult {
wfRunHooks( 'SearchResultInitFromTitle', array( $title, &$id ) );
$this->mRevision = Revision::newFromTitle(
$this->mTitle, $id, Revision::READ_NORMAL );
- if ( $this->mTitle->getNamespace() === NS_FILE )
+ if ( $this->mTitle->getNamespace() === NS_FILE ) {
$this->mImage = wfFindFile( $this->mTitle );
+ }
}
}
@@ -758,8 +829,9 @@ class SearchResult {
* @return Boolean
*/
function isBrokenTitle() {
- if ( is_null( $this->mTitle ) )
+ if ( is_null( $this->mTitle ) ) {
return true;
+ }
return false;
}
@@ -791,31 +863,35 @@ class SearchResult {
*/
protected function initText() {
if ( !isset( $this->mText ) ) {
- if ( $this->mRevision != null )
- $this->mText = $this->mRevision->getText();
- else // TODO: can we fetch raw wikitext for commons images?
+ if ( $this->mRevision != null ) {
+ $this->mText = SearchEngine::create()
+ ->getTextFromContent( $this->mTitle, $this->mRevision->getContent() );
+ } else { // TODO: can we fetch raw wikitext for commons images?
$this->mText = '';
-
+ }
}
}
/**
- * @param $terms Array: terms to highlight
+ * @param array $terms terms to highlight
* @return String: highlighted text snippet, null (and not '') if not supported
*/
function getTextSnippet( $terms ) {
- global $wgUser, $wgAdvancedSearchHighlighting;
+ global $wgAdvancedSearchHighlighting;
$this->initText();
- list( $contextlines, $contextchars ) = SearchEngine::userHighlightPrefs( $wgUser );
+
+ // TODO: make highliter take a content object. Make ContentHandler a factory for SearchHighliter.
+ list( $contextlines, $contextchars ) = SearchEngine::userHighlightPrefs();
$h = new SearchHighlighter();
- if ( $wgAdvancedSearchHighlighting )
+ if ( $wgAdvancedSearchHighlighting ) {
return $h->highlightText( $this->mText, $terms, $contextlines, $contextchars );
- else
+ } else {
return $h->highlightSimple( $this->mText, $terms, $contextlines, $contextchars );
+ }
}
/**
- * @param $terms Array: terms to highlight
+ * @param array $terms terms to highlight
* @return String: highlighted title, '' if not supported
*/
function getTitleSnippet( $terms ) {
@@ -823,7 +899,7 @@ class SearchResult {
}
/**
- * @param $terms Array: terms to highlight
+ * @param array $terms terms to highlight
* @return String: highlighted redirect name (redirect to this page), '' if none or not supported
*/
function getRedirectSnippet( $terms ) {
@@ -855,10 +931,11 @@ class SearchResult {
* @return String: timestamp
*/
function getTimestamp() {
- if ( $this->mRevision )
+ if ( $this->mRevision ) {
return $this->mRevision->getTimestamp();
- elseif ( $this->mImage )
+ } elseif ( $this->mImage ) {
return $this->mImage->getTimestamp();
+ }
return '';
}
@@ -934,7 +1011,7 @@ class SearchHighlighter {
* Default implementation of wikitext highlighting
*
* @param $text String
- * @param $terms Array: terms to highlight (unescaped)
+ * @param array $terms terms to highlight (unescaped)
* @param $contextlines Integer
* @param $contextchars Integer
* @return String
@@ -944,8 +1021,9 @@ class SearchHighlighter {
global $wgSearchHighlightBoundaries;
$fname = __METHOD__;
- if ( $text == '' )
+ if ( $text == '' ) {
return '';
+ }
// spli text into text + templates/links/tables
$spat = "/(\\{\\{)|(\\[\\[[^\\]:]+:)|(\n\\{\\|)";
@@ -962,7 +1040,7 @@ class SearchHighlighter {
}
$spat .= '/';
$textExt = array(); // text extracts
- $otherExt = array(); // other extracts
+ $otherExt = array(); // other extracts
wfProfileIn( "$fname-split" );
$start = 0;
$textLen = strlen( $text );
@@ -976,8 +1054,9 @@ class SearchHighlighter {
if ( $key == 2 ) {
// see if this is an image link
$ns = substr( $val[0], 2, - 1 );
- if ( $wgContLang->getNsIndex( $ns ) != NS_FILE )
+ if ( $wgContLang->getNsIndex( $ns ) != NS_FILE ) {
break;
+ }
}
$epat = $endPatterns[$key];
@@ -998,7 +1077,7 @@ class SearchHighlighter {
$len = strlen( $endMatches[2][0] );
$off = $endMatches[2][1];
$this->splitAndAdd( $otherExt, $count,
- substr( $text, $start, $off + $len - $start ) );
+ substr( $text, $start, $off + $len - $start ) );
$start = $off + $len;
$found = true;
break;
@@ -1111,7 +1190,7 @@ class SearchHighlighter {
// if begin of the article contains the whole phrase, show only that !!
if ( array_key_exists( $first, $snippets ) && preg_match( $pat1, $snippets[$first] )
&& $offsets[$first] < $contextchars * 2 ) {
- $snippets = array ( $first => $snippets[$first] );
+ $snippets = array( $first => $snippets[$first] );
}
// calc by how much to extend existing snippets
@@ -1131,8 +1210,8 @@ class SearchHighlighter {
// add more lines
$add = $index + 1;
while ( $len < $targetchars - 20
- && array_key_exists( $add, $all )
- && !array_key_exists( $add, $snippets ) ) {
+ && array_key_exists( $add, $all )
+ && !array_key_exists( $add, $snippets ) ) {
$offsets[$add] = 0;
$tt = "\n" . $this->extract( $all[$add], 0, $targetchars - $len, $offsets[$add] );
$extended[$add] = $tt;
@@ -1142,22 +1221,24 @@ class SearchHighlighter {
}
}
- // $snippets = array_map('htmlspecialchars', $extended);
+ // $snippets = array_map( 'htmlspecialchars', $extended );
$snippets = $extended;
$last = - 1;
$extract = '';
foreach ( $snippets as $index => $line ) {
- if ( $last == - 1 )
+ if ( $last == - 1 ) {
$extract .= $line; // first line
- elseif ( $last + 1 == $index && $offsets[$last] + strlen( $snippets[$last] ) >= strlen( $all[$last] ) )
+ } elseif ( $last + 1 == $index && $offsets[$last] + strlen( $snippets[$last] ) >= strlen( $all[$last] ) ) {
$extract .= " " . $line; // continous lines
- else
+ } else {
$extract .= '<b> ... </b>' . $line;
+ }
$last = $index;
}
- if ( $extract )
+ if ( $extract ) {
$extract .= '<b> ... </b>';
+ }
$processed = array();
foreach ( $terms as $term ) {
@@ -1177,7 +1258,7 @@ class SearchHighlighter {
/**
* Split text into lines and add it to extracts array
*
- * @param $extracts Array: index -> $line
+ * @param array $extracts index -> $line
* @param $count Integer
* @param $text String
*/
@@ -1185,8 +1266,9 @@ class SearchHighlighter {
$split = explode( "\n", $this->mCleanWikitext ? $this->removeWiki( $text ) : $text );
foreach ( $split as $line ) {
$tt = trim( $line );
- if ( $tt )
+ if ( $tt ) {
$extracts[$count++] = $tt;
+ }
}
}
@@ -1232,7 +1314,7 @@ class SearchHighlighter {
$posEnd = $end;
}
- if ( $end > $start ) {
+ if ( $end > $start ) {
return substr( $text, $start, $end - $start );
} else {
return '';
@@ -1260,8 +1342,9 @@ class SearchHighlighter {
while ( $char >= 0x80 && $char < 0xc0 ) {
// skip trailing bytes
$point++;
- if ( $point >= strlen( $text ) )
+ if ( $point >= strlen( $text ) ) {
return strlen( $text );
+ }
$char = ord( $text[$point] );
}
return $point;
@@ -1272,33 +1355,37 @@ class SearchHighlighter {
/**
* Search extracts for a pattern, and return snippets
*
- * @param $pattern String: regexp for matching lines
- * @param $extracts Array: extracts to search
+ * @param string $pattern regexp for matching lines
+ * @param array $extracts extracts to search
* @param $linesleft Integer: number of extracts to make
* @param $contextchars Integer: length of snippet
- * @param $out Array: map for highlighted snippets
- * @param $offsets Array: map of starting points of snippets
+ * @param array $out map for highlighted snippets
+ * @param array $offsets map of starting points of snippets
* @protected
*/
function process( $pattern, $extracts, &$linesleft, &$contextchars, &$out, &$offsets ) {
- if ( $linesleft == 0 )
+ if ( $linesleft == 0 ) {
return; // nothing to do
+ }
foreach ( $extracts as $index => $line ) {
- if ( array_key_exists( $index, $out ) )
+ if ( array_key_exists( $index, $out ) ) {
continue; // this line already highlighted
+ }
$m = array();
- if ( !preg_match( $pattern, $line, $m, PREG_OFFSET_CAPTURE ) )
+ if ( !preg_match( $pattern, $line, $m, PREG_OFFSET_CAPTURE ) ) {
continue;
+ }
$offset = $m[0][1];
$len = strlen( $m[0][0] );
- if ( $offset + $len < $contextchars )
+ if ( $offset + $len < $contextchars ) {
$begin = 0;
- elseif ( $len > $contextchars )
+ } elseif ( $len > $contextchars ) {
$begin = $offset;
- else
+ } else {
$begin = $offset + intval( ( $len - $contextchars ) / 2 );
+ }
$end = $begin + $contextchars;
@@ -1307,8 +1394,9 @@ class SearchHighlighter {
$out[$index] = $this->extract( $line, $begin, $end, $posBegin );
$offsets[$index] = $posBegin;
$linesleft--;
- if ( $linesleft == 0 )
+ if ( $linesleft == 0 ) {
return;
+ }
}
}
@@ -1321,12 +1409,12 @@ class SearchHighlighter {
$fname = __METHOD__;
wfProfileIn( $fname );
- // $text = preg_replace("/'{2,5}/", "", $text);
- // $text = preg_replace("/\[[a-z]+:\/\/[^ ]+ ([^]]+)\]/", "\\2", $text);
- // $text = preg_replace("/\[\[([^]|]+)\]\]/", "\\1", $text);
- // $text = preg_replace("/\[\[([^]]+\|)?([^|]]+)\]\]/", "\\2", $text);
- // $text = preg_replace("/\\{\\|(.*?)\\|\\}/", "", $text);
- // $text = preg_replace("/\\[\\[[A-Za-z_-]+:([^|]+?)\\]\\]/", "", $text);
+ // $text = preg_replace( "/'{2,5}/", "", $text );
+ // $text = preg_replace( "/\[[a-z]+:\/\/[^ ]+ ([^]]+)\]/", "\\2", $text );
+ // $text = preg_replace( "/\[\[([^]|]+)\]\]/", "\\1", $text );
+ // $text = preg_replace( "/\[\[([^]]+\|)?([^|]]+)\]\]/", "\\2", $text );
+ // $text = preg_replace( "/\\{\\|(.*?)\\|\\}/", "", $text );
+ // $text = preg_replace( "/\\[\\[[A-Za-z_-]+:([^|]+?)\\]\\]/", "", $text );
$text = preg_replace( "/\\{\\{([^|]+?)\\}\\}/", "", $text );
$text = preg_replace( "/\\{\\{([^|]+\\|)(.*?)\\}\\}/", "\\2", $text );
$text = preg_replace( "/\\[\\[([^|]+?)\\]\\]/", "\\1", $text );
@@ -1349,16 +1437,17 @@ class SearchHighlighter {
*/
function linkReplace( $matches ) {
$colon = strpos( $matches[1], ':' );
- if ( $colon === false )
+ if ( $colon === false ) {
return $matches[2]; // replace with caption
+ }
global $wgContLang;
$ns = substr( $matches[1], 0, $colon );
$index = $wgContLang->getNsIndex( $ns );
- if ( $index !== false && ( $index == NS_FILE || $index == NS_CATEGORY ) )
+ if ( $index !== false && ( $index == NS_FILE || $index == NS_CATEGORY ) ) {
return $matches[0]; // return the whole thing
- else
+ } else {
return $matches[2];
-
+ }
}
/**
@@ -1408,8 +1497,7 @@ class SearchHighlighter {
$line = htmlspecialchars( $pre . $found . $post );
$pat2 = '/(' . $terms . ")/i";
- $line = preg_replace( $pat2,
- "<span class='searchmatch'>\\1</span>", $line );
+ $line = preg_replace( $pat2, "<span class='searchmatch'>\\1</span>", $line );
$extract .= "${line}\n";
}
diff --git a/includes/search/SearchIBM_DB2.php b/includes/search/SearchIBM_DB2.php
deleted file mode 100644
index 51ed000f..00000000
--- a/includes/search/SearchIBM_DB2.php
+++ /dev/null
@@ -1,234 +0,0 @@
-<?php
-/**
- * IBM DB2 search engine
- *
- * Copyright © 2004 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Search
- */
-
-/**
- * Search engine hook base class for IBM DB2
- * @ingroup Search
- */
-class SearchIBM_DB2 extends SearchEngine {
-
- /**
- * Creates an instance of this class
- * @param $db DatabaseIbm_db2: database object
- */
- function __construct($db) {
- parent::__construct( $db );
- }
-
- /**
- * Perform a full text search query and return a result set.
- *
- * @param $term String: raw search term
- * @return SqlSearchResultSet
- */
- function searchText( $term ) {
- $resultSet = $this->db->resultObject($this->db->query($this->getQuery($this->filter($term), true)));
- return new SqlSearchResultSet($resultSet, $this->searchTerms);
- }
-
- /**
- * Perform a title-only search query and return a result set.
- *
- * @param $term String: taw search term
- * @return SqlSearchResultSet
- */
- function searchTitle($term) {
- $resultSet = $this->db->resultObject($this->db->query($this->getQuery($this->filter($term), false)));
- return new SqlSearchResultSet($resultSet, $this->searchTerms);
- }
-
-
- /**
- * Return a partial WHERE clause to exclude redirects, if so set
- * @return String
- */
- function queryRedirect() {
- if ($this->showRedirects) {
- return '';
- } else {
- return 'AND page_is_redirect=0';
- }
- }
-
- /**
- * Return a partial WHERE clause to limit the search to the given namespaces
- * @return String
- */
- function queryNamespaces() {
- if( is_null($this->namespaces) )
- return '';
- $namespaces = implode(',', $this->namespaces);
- if ($namespaces == '') {
- $namespaces = '0';
- }
- return 'AND page_namespace IN (' . $namespaces . ')';
- }
-
- /**
- * Return a LIMIT clause to limit results on the query.
- * @return String
- */
- function queryLimit( $sql ) {
- return $this->db->limitResult($sql, $this->limit, $this->offset);
- }
-
- /**
- * Does not do anything for generic search engine
- * subclasses may define this though
- * @return String
- */
- function queryRanking($filteredTerm, $fulltext) {
- // requires Net Search Extender or equivalent
- // return ' ORDER BY score(1)';
- return '';
- }
-
- /**
- * Construct the full SQL query to do the search.
- * The guts shoulds be constructed in queryMain()
- * @param $filteredTerm String
- * @param $fulltext Boolean
- * @return String
- */
- function getQuery( $filteredTerm, $fulltext ) {
- return $this->queryLimit($this->queryMain($filteredTerm, $fulltext) . ' ' .
- $this->queryRedirect() . ' ' .
- $this->queryNamespaces() . ' ' .
- $this->queryRanking( $filteredTerm, $fulltext ) . ' ');
- }
-
-
- /**
- * Picks which field to index on, depending on what type of query.
- * @param $fulltext Boolean
- * @return String
- */
- function getIndexField($fulltext) {
- return $fulltext ? 'si_text' : 'si_title';
- }
-
- /**
- * Get the base part of the search query.
- *
- * @param $filteredTerm String
- * @param $fulltext Boolean
- * @return String
- */
- function queryMain( $filteredTerm, $fulltext ) {
- $match = $this->parseQuery($filteredTerm, $fulltext);
- $page = $this->db->tableName('page');
- $searchindex = $this->db->tableName('searchindex');
- return 'SELECT page_id, page_namespace, page_title ' .
- "FROM $page,$searchindex " .
- 'WHERE page_id=si_page AND ' . $match;
- }
-
- /** @todo document
- * @return string
- */
- function parseQuery($filteredText, $fulltext) {
- global $wgContLang;
- $lc = SearchEngine::legalSearchChars();
- $this->searchTerms = array();
-
- # @todo FIXME: This doesn't handle parenthetical expressions.
- $m = array();
- $q = array();
-
- if (preg_match_all('/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
- $filteredText, $m, PREG_SET_ORDER)) {
- foreach($m as $terms) {
-
- // Search terms in all variant forms, only
- // apply on wiki with LanguageConverter
- $temp_terms = $wgContLang->autoConvertToAllVariants( $terms[2] );
- if( is_array( $temp_terms )) {
- $temp_terms = array_unique( array_values( $temp_terms ));
- foreach( $temp_terms as $t )
- $q[] = $terms[1] . $wgContLang->normalizeForSearch( $t );
- }
- else
- $q[] = $terms[1] . $wgContLang->normalizeForSearch( $terms[2] );
-
- if (!empty($terms[3])) {
- $regexp = preg_quote( $terms[3], '/' );
- if ($terms[4])
- $regexp .= "[0-9A-Za-z_]+";
- } else {
- $regexp = preg_quote(str_replace('"', '', $terms[2]), '/');
- }
- $this->searchTerms[] = $regexp;
- }
- }
-
- $searchon = $this->db->strencode(join(',', $q));
- $field = $this->getIndexField($fulltext);
-
- // requires Net Search Extender or equivalent
- //return " CONTAINS($field, '$searchon') > 0 ";
-
- return " lcase($field) LIKE lcase('%$searchon%')";
- }
-
- /**
- * Create or update the search index record for the given page.
- * Title and text should be pre-processed.
- *
- * @param $id Integer
- * @param $title String
- * @param $text String
- */
- function update($id, $title, $text) {
- $dbw = wfGetDB(DB_MASTER);
- $dbw->replace('searchindex',
- array('si_page'),
- array(
- 'si_page' => $id,
- 'si_title' => $title,
- 'si_text' => $text
- ), 'SearchIBM_DB2::update' );
- // ?
- //$dbw->query("CALL ctx_ddl.sync_index('si_text_idx')");
- //$dbw->query("CALL ctx_ddl.sync_index('si_title_idx')");
- }
-
- /**
- * Update a search index record's title only.
- * Title should be pre-processed.
- *
- * @param $id Integer
- * @param $title String
- */
- function updateTitle($id, $title) {
- $dbw = wfGetDB(DB_MASTER);
-
- $dbw->update('searchindex',
- array('si_title' => $title),
- array('si_page' => $id),
- 'SearchIBM_DB2::updateTitle',
- array());
- }
-}
diff --git a/includes/search/SearchMssql.php b/includes/search/SearchMssql.php
index 69c92ba3..cbc1a7a7 100644
--- a/includes/search/SearchMssql.php
+++ b/includes/search/SearchMssql.php
@@ -38,7 +38,7 @@ class SearchMssql extends SearchEngine {
/**
* Perform a full text search query and return a result set.
*
- * @param $term String: raw search term
+ * @param string $term raw search term
* @return MssqlSearchResultSet
* @access public
*/
@@ -50,7 +50,7 @@ class SearchMssql extends SearchEngine {
/**
* Perform a title-only search query and return a result set.
*
- * @param $term String: raw search term
+ * @param string $term raw search term
* @return MssqlSearchResultSet
* @access public
*/
@@ -59,7 +59,6 @@ class SearchMssql extends SearchEngine {
return new MssqlSearchResultSet( $resultSet, $this->searchTerms );
}
-
/**
* Return a partial WHERE clause to exclude redirects, if so set
*
@@ -78,7 +77,7 @@ class SearchMssql extends SearchEngine {
* Return a partial WHERE clause to limit the search to the given namespaces
*
* @return String
- * @private
+ * @private
*/
function queryNamespaces() {
$namespaces = implode( ',', $this->namespaces );
@@ -144,9 +143,9 @@ class SearchMssql extends SearchEngine {
*/
function queryMain( $filteredTerm, $fulltext ) {
$match = $this->parseQuery( $filteredTerm, $fulltext );
- $page = $this->db->tableName( 'page' );
+ $page = $this->db->tableName( 'page' );
$searchindex = $this->db->tableName( 'searchindex' );
-
+
return 'SELECT page_id, page_namespace, page_title, ftindex.[RANK]' .
"FROM $page,FREETEXTTABLE($searchindex , $match, LANGUAGE 'English') as ftindex " .
'WHERE page_id=ftindex.[KEY] ';
@@ -171,8 +170,9 @@ class SearchMssql extends SearchEngine {
if ( !empty( $terms[3] ) ) {
$regexp = preg_quote( $terms[3], '/' );
- if ( $terms[4] )
+ if ( $terms[4] ) {
$regexp .= "[0-9A-Za-z_]+";
+ }
} else {
$regexp = preg_quote( str_replace( '"', '', $terms[2] ), '/' );
}
@@ -192,11 +192,11 @@ class SearchMssql extends SearchEngine {
* @param $id Integer
* @param $title String
* @param $text String
- * @return bool|\ResultWrapper
+ * @return bool|ResultWrapper
*/
function update( $id, $title, $text ) {
// We store the column data as UTF-8 byte order marked binary stream
- // because we are invoking the plain text IFilter on it so that, and we want it
+ // because we are invoking the plain text IFilter on it so that, and we want it
// to properly decode the stream as UTF-8. SQL doesn't support UTF8 as a data type
// but the indexer will correctly handle it by this method. Since all we are doing
// is passing this data to the indexer and never retrieving it via PHP, this will save space
@@ -215,7 +215,7 @@ class SearchMssql extends SearchEngine {
*
* @param $id Integer
* @param $title String
- * @return bool|\ResultWrapper
+ * @return bool|ResultWrapper
*/
function updateTitle( $id, $title ) {
$table = $this->db->tableName( 'searchindex' );
@@ -248,10 +248,9 @@ class MssqlSearchResultSet extends SearchResultSet {
function next() {
$row = $this->mResultSet->fetchObject();
- if ( $row === false )
+ if ( $row === false ) {
return false;
+ }
return new SearchResult( $row );
}
}
-
-
diff --git a/includes/search/SearchMySQL.php b/includes/search/SearchMySQL.php
index 5cee03e0..b2bc1c26 100644
--- a/includes/search/SearchMySQL.php
+++ b/includes/search/SearchMySQL.php
@@ -57,12 +57,12 @@ class SearchMySQL extends SearchEngine {
# @todo FIXME: This doesn't handle parenthetical expressions.
$m = array();
- if( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
- $filteredText, $m, PREG_SET_ORDER ) ) {
- foreach( $m as $bits ) {
+ if ( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
+ $filteredText, $m, PREG_SET_ORDER ) ) {
+ foreach ( $m as $bits ) {
@list( /* all */, $modifier, $term, $nonQuoted, $wildcard ) = $bits;
- if( $nonQuoted != '' ) {
+ if ( $nonQuoted != '' ) {
$term = $nonQuoted;
$quote = '';
} else {
@@ -70,8 +70,10 @@ class SearchMySQL extends SearchEngine {
$quote = '"';
}
- if( $searchon !== '' ) $searchon .= ' ';
- if( $this->strictMatching && ($modifier == '') ) {
+ if ( $searchon !== '' ) {
+ $searchon .= ' ';
+ }
+ if ( $this->strictMatching && ( $modifier == '' ) ) {
// If we leave this out, boolean op defaults to OR which is rarely helpful.
$modifier = '+';
}
@@ -79,7 +81,7 @@ class SearchMySQL extends SearchEngine {
// Some languages such as Serbian store the input form in the search index,
// so we may need to search for matches in multiple writing system variants.
$convertedVariants = $wgContLang->autoConvertToAllVariants( $term );
- if( is_array( $convertedVariants ) ) {
+ if ( is_array( $convertedVariants ) ) {
$variants = array_unique( array_values( $convertedVariants ) );
} else {
$variants = array( $term );
@@ -99,11 +101,12 @@ class SearchMySQL extends SearchEngine {
$strippedVariants = array_unique( $strippedVariants );
$searchon .= $modifier;
- if( count( $strippedVariants) > 1 )
+ if ( count( $strippedVariants ) > 1 ) {
$searchon .= '(';
- foreach( $strippedVariants as $stripped ) {
+ }
+ foreach ( $strippedVariants as $stripped ) {
$stripped = $this->normalizeText( $stripped );
- if( $nonQuoted && strpos( $stripped, ' ' ) !== false ) {
+ if ( $nonQuoted && strpos( $stripped, ' ' ) !== false ) {
// Hack for Chinese: we need to toss in quotes for
// multiple-character phrases since normalizeForSearch()
// added spaces between them to make word breaks.
@@ -111,8 +114,9 @@ class SearchMySQL extends SearchEngine {
}
$searchon .= "$quote$stripped$quote$wildcard ";
}
- if( count( $strippedVariants) > 1 )
+ if ( count( $strippedVariants ) > 1 ) {
$searchon .= ')';
+ }
// Match individual terms or quoted phrase in result highlighting...
// Note that variants will be introduced in a later stage for highlighting!
@@ -134,8 +138,8 @@ class SearchMySQL extends SearchEngine {
global $wgContLang;
$regex = preg_quote( $string, '/' );
- if( $wgContLang->hasWordBreaks() ) {
- if( $wildcard ) {
+ if ( $wgContLang->hasWordBreaks() ) {
+ if ( $wildcard ) {
// Don't cut off the final bit!
$regex = "\b$regex";
} else {
@@ -156,7 +160,7 @@ class SearchMySQL extends SearchEngine {
/**
* Perform a full text search query and return a result set.
*
- * @param $term String: raw search term
+ * @param string $term raw search term
* @return MySQLSearchResultSet
*/
function searchText( $term ) {
@@ -166,7 +170,7 @@ class SearchMySQL extends SearchEngine {
/**
* Perform a title-only search query and return a result set.
*
- * @param $term String: raw search term
+ * @param string $term raw search term
* @return MySQLSearchResultSet
*/
function searchTitle( $term ) {
@@ -177,7 +181,9 @@ class SearchMySQL extends SearchEngine {
global $wgCountTotalSearchHits;
// This seems out of place, why is this called with empty term?
- if ( trim( $term ) === '' ) return null;
+ if ( trim( $term ) === '' ) {
+ return null;
+ }
$filteredTerm = $this->filter( $term );
$query = $this->getQuery( $filteredTerm, $fulltext );
@@ -187,7 +193,7 @@ class SearchMySQL extends SearchEngine {
);
$total = null;
- if( $wgCountTotalSearchHits ) {
+ if ( $wgCountTotalSearchHits ) {
$query = $this->getCountQuery( $filteredTerm, $fulltext );
$totalResult = $this->db->select(
$query['tables'], $query['fields'], $query['conds'],
@@ -195,7 +201,7 @@ class SearchMySQL extends SearchEngine {
);
$row = $totalResult->fetchObject();
- if( $row ) {
+ if ( $row ) {
$total = intval( $row->c );
}
$totalResult->free();
@@ -205,12 +211,11 @@ class SearchMySQL extends SearchEngine {
}
public function supports( $feature ) {
- switch( $feature ) {
- case 'list-redirects':
+ switch ( $feature ) {
case 'title-suffix-filter':
return true;
default:
- return false;
+ return parent::supports( $feature );
}
}
@@ -221,9 +226,9 @@ class SearchMySQL extends SearchEngine {
*/
protected function queryFeatures( &$query ) {
foreach ( $this->features as $feature => $value ) {
- if ( $feature === 'list-redirects' && !$value ) {
+ if ( $feature === 'list-redirects' && !$value ) {
$query['conds']['page_is_redirect'] = 0;
- } elseif( $feature === 'title-suffix-filter' && $value ) {
+ } elseif ( $feature === 'title-suffix-filter' && $value ) {
$query['conds'][] = 'page_title' . $this->db->buildLike( $this->db->anyString(), $value );
}
}
@@ -358,12 +363,25 @@ class SearchMySQL extends SearchEngine {
$dbw->update( 'searchindex',
array( 'si_title' => $this->normalizeText( $title ) ),
- array( 'si_page' => $id ),
+ array( 'si_page' => $id ),
__METHOD__,
array( $dbw->lowPriorityOption() ) );
}
/**
+ * Delete an indexed page
+ * Title should be pre-processed.
+ *
+ * @param Integer $id Page id that was deleted
+ * @param String $title Title of page that was deleted
+ */
+ function delete( $id, $title ) {
+ $dbw = wfGetDB( DB_MASTER );
+
+ $dbw->delete( 'searchindex', array( 'si_page' => $id ), __METHOD__ );
+ }
+
+ /**
* Converts some characters for MySQL's indexing to grok it correctly,
* and pads short words to overcome limitations.
* @return mixed|string
@@ -386,7 +404,7 @@ class SearchMySQL extends SearchEngine {
// ignores short words... Pad them so we can pass them
// through without reconfiguring the server...
$minLength = $this->minSearchLength();
- if( $minLength > 1 ) {
+ if ( $minLength > 1 ) {
$n = $minLength - 1;
$out = preg_replace(
"/\b(\w{1,$n})\b/",
@@ -427,7 +445,7 @@ class SearchMySQL extends SearchEngine {
* @return int
*/
protected function minSearchLength() {
- if( is_null( self::$mMinSearchLength ) ) {
+ if ( is_null( self::$mMinSearchLength ) ) {
$sql = "SHOW GLOBAL VARIABLES LIKE 'ft\\_min\\_word\\_len'";
$dbr = wfGetDB( DB_SLAVE );
@@ -435,7 +453,7 @@ class SearchMySQL extends SearchEngine {
$row = $result->fetchObject();
$result->free();
- if( $row && $row->Variable_name == 'ft_min_word_len' ) {
+ if ( $row && $row->Variable_name == 'ft_min_word_len' ) {
self::$mMinSearchLength = intval( $row->Value );
} else {
self::$mMinSearchLength = 0;
@@ -449,7 +467,7 @@ class SearchMySQL extends SearchEngine {
* @ingroup Search
*/
class MySQLSearchResultSet extends SqlSearchResultSet {
- function __construct( $resultSet, $terms, $totalHits=null ) {
+ function __construct( $resultSet, $terms, $totalHits = null ) {
parent::__construct( $resultSet, $terms );
$this->mTotalHits = $totalHits;
}
diff --git a/includes/search/SearchOracle.php b/includes/search/SearchOracle.php
index a2db52f3..a8479654 100644
--- a/includes/search/SearchOracle.php
+++ b/includes/search/SearchOracle.php
@@ -29,77 +29,80 @@
* @ingroup Search
*/
class SearchOracle extends SearchEngine {
-
- private $reservedWords = array ('ABOUT' => 1,
- 'ACCUM' => 1,
- 'AND' => 1,
- 'BT' => 1,
- 'BTG' => 1,
- 'BTI' => 1,
- 'BTP' => 1,
- 'FUZZY' => 1,
- 'HASPATH' => 1,
- 'INPATH' => 1,
- 'MINUS' => 1,
- 'NEAR' => 1,
- 'NOT' => 1,
- 'NT' => 1,
- 'NTG' => 1,
- 'NTI' => 1,
- 'NTP' => 1,
- 'OR' => 1,
- 'PT' => 1,
- 'RT' => 1,
- 'SQE' => 1,
- 'SYN' => 1,
- 'TR' => 1,
- 'TRSYN' => 1,
- 'TT' => 1,
- 'WITHIN' => 1);
+
+ private $reservedWords = array(
+ 'ABOUT' => 1,
+ 'ACCUM' => 1,
+ 'AND' => 1,
+ 'BT' => 1,
+ 'BTG' => 1,
+ 'BTI' => 1,
+ 'BTP' => 1,
+ 'FUZZY' => 1,
+ 'HASPATH' => 1,
+ 'INPATH' => 1,
+ 'MINUS' => 1,
+ 'NEAR' => 1,
+ 'NOT' => 1,
+ 'NT' => 1,
+ 'NTG' => 1,
+ 'NTI' => 1,
+ 'NTP' => 1,
+ 'OR' => 1,
+ 'PT' => 1,
+ 'RT' => 1,
+ 'SQE' => 1,
+ 'SYN' => 1,
+ 'TR' => 1,
+ 'TRSYN' => 1,
+ 'TT' => 1,
+ 'WITHIN' => 1,
+ );
/**
* Creates an instance of this class
* @param $db DatabasePostgres: database object
*/
- function __construct($db) {
+ function __construct( $db ) {
parent::__construct( $db );
}
/**
* Perform a full text search query and return a result set.
*
- * @param $term String: raw search term
+ * @param string $term raw search term
* @return SqlSearchResultSet
*/
function searchText( $term ) {
- if ($term == '')
- return new SqlSearchResultSet(false, '');
+ if ( $term == '' ) {
+ return new SqlSearchResultSet( false, '' );
+ }
- $resultSet = $this->db->resultObject($this->db->query($this->getQuery($this->filter($term), true)));
- return new SqlSearchResultSet($resultSet, $this->searchTerms);
+ $resultSet = $this->db->resultObject( $this->db->query( $this->getQuery( $this->filter( $term ), true ) ) );
+ return new SqlSearchResultSet( $resultSet, $this->searchTerms );
}
/**
* Perform a title-only search query and return a result set.
*
- * @param $term String: raw search term
+ * @param string $term raw search term
* @return SqlSearchResultSet
*/
- function searchTitle($term) {
- if ($term == '')
- return new SqlSearchResultSet(false, '');
+ function searchTitle( $term ) {
+ if ( $term == '' ) {
+ return new SqlSearchResultSet( false, '' );
+ }
- $resultSet = $this->db->resultObject($this->db->query($this->getQuery($this->filter($term), false)));
- return new MySQLSearchResultSet($resultSet, $this->searchTerms);
+ $resultSet = $this->db->resultObject( $this->db->query( $this->getQuery( $this->filter( $term ), false ) ) );
+ return new MySQLSearchResultSet( $resultSet, $this->searchTerms );
}
-
/**
* Return a partial WHERE clause to exclude redirects, if so set
* @return String
*/
function queryRedirect() {
- if ($this->showRedirects) {
+ if ( $this->showRedirects ) {
return '';
} else {
return 'AND page_is_redirect=0';
@@ -111,8 +114,9 @@ class SearchOracle extends SearchEngine {
* @return String
*/
function queryNamespaces() {
- if( is_null($this->namespaces) )
+ if ( is_null( $this->namespaces ) ) {
return '';
+ }
if ( !count( $this->namespaces ) ) {
$namespaces = '0';
} else {
@@ -129,7 +133,7 @@ class SearchOracle extends SearchEngine {
* @return String
*/
function queryLimit( $sql ) {
- return $this->db->limitResult($sql, $this->limit, $this->offset);
+ return $this->db->limitResult( $sql, $this->limit, $this->offset );
}
/**
@@ -150,19 +154,18 @@ class SearchOracle extends SearchEngine {
* @return String
*/
function getQuery( $filteredTerm, $fulltext ) {
- return $this->queryLimit($this->queryMain($filteredTerm, $fulltext) . ' ' .
+ return $this->queryLimit( $this->queryMain( $filteredTerm, $fulltext ) . ' ' .
$this->queryRedirect() . ' ' .
$this->queryNamespaces() . ' ' .
- $this->queryRanking( $filteredTerm, $fulltext ) . ' ');
+ $this->queryRanking( $filteredTerm, $fulltext ) . ' ' );
}
-
/**
* Picks which field to index on, depending on what type of query.
* @param $fulltext Boolean
* @return String
*/
- function getIndexField($fulltext) {
+ function getIndexField( $fulltext ) {
return $fulltext ? 'si_text' : 'si_title';
}
@@ -174,9 +177,9 @@ class SearchOracle extends SearchEngine {
* @return String
*/
function queryMain( $filteredTerm, $fulltext ) {
- $match = $this->parseQuery($filteredTerm, $fulltext);
- $page = $this->db->tableName('page');
- $searchindex = $this->db->tableName('searchindex');
+ $match = $this->parseQuery( $filteredTerm, $fulltext );
+ $page = $this->db->tableName( 'page' );
+ $searchindex = $this->db->tableName( 'searchindex' );
return 'SELECT page_id, page_namespace, page_title ' .
"FROM $page,$searchindex " .
'WHERE page_id=si_page AND ' . $match;
@@ -187,7 +190,7 @@ class SearchOracle extends SearchEngine {
* as part of a WHERE clause
* @return string
*/
- function parseQuery($filteredText, $fulltext) {
+ function parseQuery( $filteredText, $fulltext ) {
global $wgContLang;
$lc = SearchEngine::legalSearchChars();
$this->searchTerms = array();
@@ -195,44 +198,44 @@ class SearchOracle extends SearchEngine {
# @todo FIXME: This doesn't handle parenthetical expressions.
$m = array();
$searchon = '';
- if (preg_match_all('/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
- $filteredText, $m, PREG_SET_ORDER)) {
- foreach($m as $terms) {
+ if ( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
+ $filteredText, $m, PREG_SET_ORDER ) ) {
+ foreach ( $m as $terms ) {
// Search terms in all variant forms, only
// apply on wiki with LanguageConverter
$temp_terms = $wgContLang->autoConvertToAllVariants( $terms[2] );
- if( is_array( $temp_terms )) {
- $temp_terms = array_unique( array_values( $temp_terms ));
- foreach( $temp_terms as $t ) {
- $searchon .= ($terms[1] == '-' ? ' ~' : ' & ') . $this->escapeTerm( $t );
+ if ( is_array( $temp_terms ) ) {
+ $temp_terms = array_unique( array_values( $temp_terms ) );
+ foreach ( $temp_terms as $t ) {
+ $searchon .= ( $terms[1] == '-' ? ' ~' : ' & ' ) . $this->escapeTerm( $t );
}
}
else {
- $searchon .= ($terms[1] == '-' ? ' ~' : ' & ') . $this->escapeTerm( $terms[2] );
+ $searchon .= ( $terms[1] == '-' ? ' ~' : ' & ' ) . $this->escapeTerm( $terms[2] );
}
- if (!empty($terms[3])) {
+ if ( !empty( $terms[3] ) ) {
$regexp = preg_quote( $terms[3], '/' );
- if ($terms[4])
+ if ( $terms[4] ) {
$regexp .= "[0-9A-Za-z_]+";
+ }
} else {
- $regexp = preg_quote(str_replace('"', '', $terms[2]), '/');
+ $regexp = preg_quote( str_replace( '"', '', $terms[2] ), '/' );
}
$this->searchTerms[] = $regexp;
}
}
-
- $searchon = $this->db->addQuotes(ltrim($searchon, ' &'));
- $field = $this->getIndexField($fulltext);
+ $searchon = $this->db->addQuotes( ltrim( $searchon, ' &' ) );
+ $field = $this->getIndexField( $fulltext );
return " CONTAINS($field, $searchon, 1) > 0 ";
}
- private function escapeTerm($t) {
+ private function escapeTerm( $t ) {
global $wgContLang;
- $t = $wgContLang->normalizeForSearch($t);
- $t = isset($this->reservedWords[strtoupper($t)]) ? '{'.$t.'}' : $t;
- $t = preg_replace('/^"(.*)"$/', '($1)', $t);
- $t = preg_replace('/([-&|])/', '\\\\$1', $t);
+ $t = $wgContLang->normalizeForSearch( $t );
+ $t = isset( $this->reservedWords[strtoupper( $t )] ) ? '{' . $t . '}' : $t;
+ $t = preg_replace( '/^"(.*)"$/', '($1)', $t );
+ $t = preg_replace( '/([-&|])/', '\\\\$1', $t );
return $t;
}
/**
@@ -243,10 +246,10 @@ class SearchOracle extends SearchEngine {
* @param $title String
* @param $text String
*/
- function update($id, $title, $text) {
- $dbw = wfGetDB(DB_MASTER);
- $dbw->replace('searchindex',
- array('si_page'),
+ function update( $id, $title, $text ) {
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->replace( 'searchindex',
+ array( 'si_page' ),
array(
'si_page' => $id,
'si_title' => $title,
@@ -254,13 +257,13 @@ class SearchOracle extends SearchEngine {
), 'SearchOracle::update' );
// Sync the index
- // We need to specify the DB name (i.e. user/schema) here so that
+ // We need to specify the DB name (i.e. user/schema) here so that
// it can work from the installer, where
// ALTER SESSION SET CURRENT_SCHEMA = ...
// was used.
- $dbw->query( "CALL ctx_ddl.sync_index(" .
+ $dbw->query( "CALL ctx_ddl.sync_index(" .
$dbw->addQuotes( $dbw->getDBname() . '.' . $dbw->tableName( 'si_text_idx', 'raw' ) ) . ")" );
- $dbw->query( "CALL ctx_ddl.sync_index(" .
+ $dbw->query( "CALL ctx_ddl.sync_index(" .
$dbw->addQuotes( $dbw->getDBname() . '.' . $dbw->tableName( 'si_title_idx', 'raw' ) ) . ")" );
}
@@ -271,17 +274,16 @@ class SearchOracle extends SearchEngine {
* @param $id Integer
* @param $title String
*/
- function updateTitle($id, $title) {
- $dbw = wfGetDB(DB_MASTER);
+ function updateTitle( $id, $title ) {
+ $dbw = wfGetDB( DB_MASTER );
- $dbw->update('searchindex',
- array('si_title' => $title),
- array('si_page' => $id),
+ $dbw->update( 'searchindex',
+ array( 'si_title' => $title ),
+ array( 'si_page' => $id ),
'SearchOracle::updateTitle',
- array());
+ array() );
}
-
public static function legalSearchChars() {
return "\"" . parent::legalSearchChars();
}
diff --git a/includes/search/SearchPostgres.php b/includes/search/SearchPostgres.php
index 68648894..7f19ed13 100644
--- a/includes/search/SearchPostgres.php
+++ b/includes/search/SearchPostgres.php
@@ -47,15 +47,15 @@ class SearchPostgres extends SearchEngine {
* Currently searches a page's current title (page.page_title) and
* latest revision article text (pagecontent.old_text)
*
- * @param $term String: raw search term
+ * @param string $term raw search term
* @return PostgresSearchResultSet
*/
function searchTitle( $term ) {
- $q = $this->searchQuery( $term , 'titlevector', 'page_title' );
- $olderror = error_reporting(E_ERROR);
+ $q = $this->searchQuery( $term, 'titlevector', 'page_title' );
+ $olderror = error_reporting( E_ERROR );
$resultSet = $this->db->resultObject( $this->db->query( $q, 'SearchPostgres', true ) );
- error_reporting($olderror);
- if (!$resultSet) {
+ error_reporting( $olderror );
+ if ( !$resultSet ) {
// Needed for "Query requires full scan, GIN doesn't support it"
return new SearchResultTooMany();
}
@@ -64,10 +64,10 @@ class SearchPostgres extends SearchEngine {
function searchText( $term ) {
$q = $this->searchQuery( $term, 'textvector', 'old_text' );
- $olderror = error_reporting(E_ERROR);
+ $olderror = error_reporting( E_ERROR );
$resultSet = $this->db->resultObject( $this->db->query( $q, 'SearchPostgres', true ) );
- error_reporting($olderror);
- if (!$resultSet) {
+ error_reporting( $olderror );
+ if ( !$resultSet ) {
return new SearchResultTooMany();
}
return new PostgresSearchResultSet( $resultSet, $this->searchTerms );
@@ -86,29 +86,29 @@ class SearchPostgres extends SearchEngine {
wfDebug( "parseQuery received: $term \n" );
## No backslashes allowed
- $term = preg_replace('/\\\/', '', $term);
+ $term = preg_replace( '/\\\/', '', $term );
## Collapse parens into nearby words:
- $term = preg_replace('/\s*\(\s*/', ' (', $term);
- $term = preg_replace('/\s*\)\s*/', ') ', $term);
+ $term = preg_replace( '/\s*\(\s*/', ' (', $term );
+ $term = preg_replace( '/\s*\)\s*/', ') ', $term );
## Treat colons as word separators:
- $term = preg_replace('/:/', ' ', $term);
+ $term = preg_replace( '/:/', ' ', $term );
$searchstring = '';
$m = array();
- if( preg_match_all('/([-!]?)(\S+)\s*/', $term, $m, PREG_SET_ORDER ) ) {
- foreach( $m as $terms ) {
- if (strlen($terms[1])) {
+ if ( preg_match_all( '/([-!]?)(\S+)\s*/', $term, $m, PREG_SET_ORDER ) ) {
+ foreach ( $m as $terms ) {
+ if ( strlen( $terms[1] ) ) {
$searchstring .= ' & !';
}
- if (strtolower($terms[2]) === 'and') {
+ if ( strtolower( $terms[2] ) === 'and' ) {
$searchstring .= ' & ';
}
- elseif (strtolower($terms[2]) === 'or' or $terms[2] === '|') {
+ elseif ( strtolower( $terms[2] ) === 'or' or $terms[2] === '|' ) {
$searchstring .= ' | ';
}
- elseif (strtolower($terms[2]) === 'not') {
+ elseif ( strtolower( $terms[2] ) === 'not' ) {
$searchstring .= ' & !';
}
else {
@@ -118,22 +118,22 @@ class SearchPostgres extends SearchEngine {
}
## Strip out leading junk
- $searchstring = preg_replace('/^[\s\&\|]+/', '', $searchstring);
+ $searchstring = preg_replace( '/^[\s\&\|]+/', '', $searchstring );
## Remove any doubled-up operators
- $searchstring = preg_replace('/([\!\&\|]) +(?:[\&\|] +)+/', "$1 ", $searchstring);
+ $searchstring = preg_replace( '/([\!\&\|]) +(?:[\&\|] +)+/', "$1 ", $searchstring );
## Remove any non-spaced operators (e.g. "Zounds!")
- $searchstring = preg_replace('/([^ ])[\!\&\|]/', "$1", $searchstring);
+ $searchstring = preg_replace( '/([^ ])[\!\&\|]/', "$1", $searchstring );
## Remove any trailing whitespace or operators
- $searchstring = preg_replace('/[\s\!\&\|]+$/', '', $searchstring);
+ $searchstring = preg_replace( '/[\s\!\&\|]+$/', '', $searchstring );
## Remove unnecessary quotes around everything
- $searchstring = preg_replace('/^[\'"](.*)[\'"]$/', "$1", $searchstring);
+ $searchstring = preg_replace( '/^[\'"](.*)[\'"]$/', "$1", $searchstring );
## Quote the whole thing
- $searchstring = $this->db->addQuotes($searchstring);
+ $searchstring = $this->db->addQuotes( $searchstring );
wfDebug( "parseQuery returned: $searchstring \n" );
@@ -154,42 +154,43 @@ class SearchPostgres extends SearchEngine {
## We need a separate query here so gin does not complain about empty searches
$SQL = "SELECT to_tsquery($searchstring)";
- $res = $this->db->query($SQL);
- if (!$res) {
+ $res = $this->db->query( $SQL );
+ if ( !$res ) {
## TODO: Better output (example to catch: one 'two)
- die ("Sorry, that was not a valid search string. Please go back and try again");
+ die( "Sorry, that was not a valid search string. Please go back and try again" );
}
$top = $res->fetchRow();
$top = $top[0];
- if ($top === "") { ## e.g. if only stopwords are used XXX return something better
- $query = "SELECT page_id, page_namespace, page_title, 0 AS score ".
+ if ( $top === "" ) { ## e.g. if only stopwords are used XXX return something better
+ $query = "SELECT page_id, page_namespace, page_title, 0 AS score " .
"FROM page p, revision r, pagecontent c WHERE p.page_latest = r.rev_id " .
"AND r.rev_text_id = c.old_id AND 1=0";
}
else {
$m = array();
- if( preg_match_all("/'([^']+)'/", $top, $m, PREG_SET_ORDER ) ) {
- foreach( $m as $terms ) {
+ if ( preg_match_all( "/'([^']+)'/", $top, $m, PREG_SET_ORDER ) ) {
+ foreach ( $m as $terms ) {
$this->searchTerms[$terms[1]] = $terms[1];
}
}
- $query = "SELECT page_id, page_namespace, page_title, ".
- "ts_rank($fulltext, to_tsquery($searchstring), 5) AS score ".
+ $query = "SELECT page_id, page_namespace, page_title, " .
+ "ts_rank($fulltext, to_tsquery($searchstring), 5) AS score " .
"FROM page p, revision r, pagecontent c WHERE p.page_latest = r.rev_id " .
"AND r.rev_text_id = c.old_id AND $fulltext @@ to_tsquery($searchstring)";
}
## Redirects
- if (! $this->showRedirects)
+ if ( !$this->showRedirects ) {
$query .= ' AND page_is_redirect = 0';
+ }
## Namespaces - defaults to 0
- if( !is_null($this->namespaces) ){ // null -> search all
- if ( count($this->namespaces) < 1)
+ if ( !is_null( $this->namespaces ) ) { // null -> search all
+ if ( count( $this->namespaces ) < 1 ) {
$query .= ' AND page_namespace = 0';
- else {
+ } else {
$namespaces = $this->db->makeList( $this->namespaces );
$query .= " AND page_namespace IN ($namespaces)";
}
@@ -208,10 +209,10 @@ class SearchPostgres extends SearchEngine {
function update( $pageid, $title, $text ) {
## We don't want to index older revisions
- $SQL = "UPDATE pagecontent SET textvector = NULL WHERE old_id IN ".
+ $SQL = "UPDATE pagecontent SET textvector = NULL WHERE old_id IN " .
"(SELECT rev_text_id FROM revision WHERE rev_page = " . intval( $pageid ) .
" ORDER BY rev_text_id DESC OFFSET 1)";
- $this->db->query($SQL);
+ $this->db->query( $SQL );
return true;
}
@@ -226,7 +227,7 @@ class SearchPostgres extends SearchEngine {
*/
class PostgresSearchResult extends SearchResult {
function __construct( $row ) {
- parent::__construct($row);
+ parent::__construct( $row );
$this->score = $row->score;
}
function getScore() {
@@ -244,7 +245,7 @@ class PostgresSearchResultSet extends SqlSearchResultSet {
function next() {
$row = $this->mResultSet->fetchObject();
- if( $row === false ) {
+ if ( $row === false ) {
return false;
} else {
return new PostgresSearchResult( $row );
diff --git a/includes/search/SearchSqlite.php b/includes/search/SearchSqlite.php
index e52e4fe3..554181f6 100644
--- a/includes/search/SearchSqlite.php
+++ b/includes/search/SearchSqlite.php
@@ -61,12 +61,12 @@ class SearchSqlite extends SearchEngine {
$this->searchTerms = array();
$m = array();
- if( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
- $filteredText, $m, PREG_SET_ORDER ) ) {
- foreach( $m as $bits ) {
+ if ( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
+ $filteredText, $m, PREG_SET_ORDER ) ) {
+ foreach ( $m as $bits ) {
@list( /* all */, $modifier, $term, $nonQuoted, $wildcard ) = $bits;
- if( $nonQuoted != '' ) {
+ if ( $nonQuoted != '' ) {
$term = $nonQuoted;
$quote = '';
} else {
@@ -74,14 +74,14 @@ class SearchSqlite extends SearchEngine {
$quote = '"';
}
- if( $searchon !== '' ) {
+ if ( $searchon !== '' ) {
$searchon .= ' ';
}
// Some languages such as Serbian store the input form in the search index,
// so we may need to search for matches in multiple writing system variants.
$convertedVariants = $wgContLang->autoConvertToAllVariants( $term );
- if( is_array( $convertedVariants ) ) {
+ if ( is_array( $convertedVariants ) ) {
$variants = array_unique( array_values( $convertedVariants ) );
} else {
$variants = array( $term );
@@ -101,10 +101,11 @@ class SearchSqlite extends SearchEngine {
$strippedVariants = array_unique( $strippedVariants );
$searchon .= $modifier;
- if( count( $strippedVariants) > 1 )
+ if ( count( $strippedVariants ) > 1 ) {
$searchon .= '(';
- foreach( $strippedVariants as $stripped ) {
- if( $nonQuoted && strpos( $stripped, ' ' ) !== false ) {
+ }
+ foreach ( $strippedVariants as $stripped ) {
+ if ( $nonQuoted && strpos( $stripped, ' ' ) !== false ) {
// Hack for Chinese: we need to toss in quotes for
// multiple-character phrases since normalizeForSearch()
// added spaces between them to make word breaks.
@@ -112,8 +113,9 @@ class SearchSqlite extends SearchEngine {
}
$searchon .= "$quote$stripped$quote$wildcard ";
}
- if( count( $strippedVariants) > 1 )
+ if ( count( $strippedVariants ) > 1 ) {
$searchon .= ')';
+ }
// Match individual terms or quoted phrase in result highlighting...
// Note that variants will be introduced in a later stage for highlighting!
@@ -134,8 +136,8 @@ class SearchSqlite extends SearchEngine {
global $wgContLang;
$regex = preg_quote( $string, '/' );
- if( $wgContLang->hasWordBreaks() ) {
- if( $wildcard ) {
+ if ( $wgContLang->hasWordBreaks() ) {
+ if ( $wildcard ) {
// Don't cut off the final bit!
$regex = "\b$regex";
} else {
@@ -156,7 +158,7 @@ class SearchSqlite extends SearchEngine {
/**
* Perform a full text search query and return a result set.
*
- * @param $term String: raw search term
+ * @param string $term raw search term
* @return SqliteSearchResultSet
*/
function searchText( $term ) {
@@ -166,7 +168,7 @@ class SearchSqlite extends SearchEngine {
/**
* Perform a title-only search query and return a result set.
*
- * @param $term String: raw search term
+ * @param string $term raw search term
* @return SqliteSearchResultSet
*/
function searchTitle( $term ) {
@@ -184,10 +186,10 @@ class SearchSqlite extends SearchEngine {
$resultSet = $this->db->query( $this->getQuery( $filteredTerm, $fulltext ) );
$total = null;
- if( $wgCountTotalSearchHits ) {
+ if ( $wgCountTotalSearchHits ) {
$totalResult = $this->db->query( $this->getCountQuery( $filteredTerm, $fulltext ) );
$row = $totalResult->fetchObject();
- if( $row ) {
+ if ( $row ) {
$total = intval( $row->c );
}
$totalResult->free();
@@ -196,13 +198,12 @@ class SearchSqlite extends SearchEngine {
return new SqliteSearchResultSet( $resultSet, $this->searchTerms, $total );
}
-
/**
* Return a partial WHERE clause to exclude redirects, if so set
* @return String
*/
function queryRedirect() {
- if( $this->showRedirects ) {
+ if ( $this->showRedirects ) {
return '';
} else {
return 'AND page_is_redirect=0';
@@ -214,8 +215,9 @@ class SearchSqlite extends SearchEngine {
* @return String
*/
function queryNamespaces() {
- if( is_null($this->namespaces) )
+ if ( is_null( $this->namespaces ) ) {
return ''; # search all
+ }
if ( !count( $this->namespaces ) ) {
$namespaces = '0';
} else {
@@ -266,7 +268,7 @@ class SearchSqlite extends SearchEngine {
*/
function queryMain( $filteredTerm, $fulltext ) {
$match = $this->parseQuery( $filteredTerm, $fulltext );
- $page = $this->db->tableName( 'page' );
+ $page = $this->db->tableName( 'page' );
$searchindex = $this->db->tableName( 'searchindex' );
return "SELECT $searchindex.rowid, page_namespace, page_title " .
"FROM $page,$searchindex " .
@@ -275,7 +277,7 @@ class SearchSqlite extends SearchEngine {
function getCountQuery( $filteredTerm, $fulltext ) {
$match = $this->parseQuery( $filteredTerm, $fulltext );
- $page = $this->db->tableName( 'page' );
+ $page = $this->db->tableName( 'page' );
$searchindex = $this->db->tableName( 'searchindex' );
return "SELECT COUNT(*) AS c " .
"FROM $page,$searchindex " .
@@ -296,7 +298,7 @@ class SearchSqlite extends SearchEngine {
if ( !$this->fulltextSearchSupported() ) {
return;
}
- // @todo: find a method to do it in a single request,
+ // @todo find a method to do it in a single request,
// couldn't do it so far due to typelessness of FTS3 tables.
$dbw = wfGetDB( DB_MASTER );
@@ -317,7 +319,7 @@ class SearchSqlite extends SearchEngine {
* @param $id Integer
* @param $title String
*/
- function updateTitle( $id, $title ) {
+ function updateTitle( $id, $title ) {
if ( !$this->fulltextSearchSupported() ) {
return;
}
@@ -325,7 +327,7 @@ class SearchSqlite extends SearchEngine {
$dbw->update( 'searchindex',
array( 'si_title' => $title ),
- array( 'rowid' => $id ),
+ array( 'rowid' => $id ),
__METHOD__ );
}
}
@@ -334,7 +336,7 @@ class SearchSqlite extends SearchEngine {
* @ingroup Search
*/
class SqliteSearchResultSet extends SqlSearchResultSet {
- function __construct( $resultSet, $terms, $totalHits=null ) {
+ function __construct( $resultSet, $terms, $totalHits = null ) {
parent::__construct( $resultSet, $terms );
$this->mTotalHits = $totalHits;
}
diff --git a/includes/search/SearchUpdate.php b/includes/search/SearchUpdate.php
index 40dd36c2..82a413e9 100644
--- a/includes/search/SearchUpdate.php
+++ b/includes/search/SearchUpdate.php
@@ -29,52 +29,114 @@
* @ingroup Search
*/
class SearchUpdate implements DeferrableUpdate {
+ /**
+ * Page id being updated
+ * @var int
+ */
+ private $id = 0;
+
+ /**
+ * Title we're updating
+ * @var Title
+ */
+ private $title;
+
+ /**
+ * Content of the page (not text)
+ * @var Content|false
+ */
+ private $content;
+
+ /**
+ * Constructor
+ *
+ * @param int $id Page id to update
+ * @param Title|string $title Title of page to update
+ * @param Content|string|false $c Content of the page to update.
+ * If a Content object, text will be gotten from it. String is for back-compat.
+ * Passing false tells the backend to just update the title, not the content
+ */
+ public function __construct( $id, $title, $c = false ) {
+ if ( is_string( $title ) ) {
+ $nt = Title::newFromText( $title );
+ } else {
+ $nt = $title;
+ }
- private $mId = 0, $mNamespace, $mTitle, $mText;
- private $mTitleWords;
-
- function __construct( $id, $title, $text = false ) {
- $nt = Title::newFromText( $title );
- if( $nt ) {
- $this->mId = $id;
- $this->mText = $text;
-
- $this->mNamespace = $nt->getNamespace();
- $this->mTitle = $nt->getText(); # Discard namespace
-
- $this->mTitleWords = $this->mTextWords = array();
+ if ( $nt ) {
+ $this->id = $id;
+ // is_string() check is back-compat for ApprovedRevs
+ if ( is_string( $c ) ) {
+ $this->content = new TextContent( $c );
+ } else {
+ $this->content = $c ?: false;
+ }
+ $this->title = $nt;
} else {
wfDebug( "SearchUpdate object created with invalid title '$title'\n" );
}
}
- function doUpdate() {
- global $wgContLang, $wgDisableSearchUpdate;
+ /**
+ * Perform actual update for the entry
+ */
+ public function doUpdate() {
+ global $wgDisableSearchUpdate;
- if( $wgDisableSearchUpdate || !$this->mId ) {
+ if ( $wgDisableSearchUpdate || !$this->id ) {
return;
}
wfProfileIn( __METHOD__ );
- $search = SearchEngine::create();
- $lc = SearchEngine::legalSearchChars() . '&#;';
+ $page = WikiPage::newFromId( $this->id, WikiPage::READ_LATEST );
+ $indexTitle = Title::indexTitle( $this->title->getNamespace(), $this->title->getText() );
- if( $this->mText === false ) {
- $search->updateTitle($this->mId,
- $search->normalizeText( Title::indexTitle( $this->mNamespace, $this->mTitle ) ) );
- wfProfileOut( __METHOD__ );
- return;
+ foreach ( SearchEngine::getSearchTypes() as $type ) {
+ $search = SearchEngine::create( $type );
+ if ( !$search->supports( 'search-update' ) ) {
+ continue;
+ }
+
+ $normalTitle = $search->normalizeText( $indexTitle );
+
+ if ( $page === null ) {
+ $search->delete( $this->id, $normalTitle );
+ continue;
+ } elseif ( $this->content === false ) {
+ $search->updateTitle( $this->id, $normalTitle );
+ continue;
+ }
+
+ $text = $search->getTextFromContent( $this->title, $this->content );
+ if ( !$search->textAlreadyUpdatedForIndex() ) {
+ $text = self::updateText( $text );
+ }
+
+ # Perform the actual update
+ $search->update( $this->id, $normalTitle, $search->normalizeText( $text ) );
}
+ wfProfileOut( __METHOD__ );
+ }
+
+ /**
+ * Clean text for indexing. Only really suitable for indexing in databases.
+ * If you're using a real search engine, you'll probably want to override
+ * this behavior and do something nicer with the original wikitext.
+ */
+ public static function updateText( $text ) {
+ global $wgContLang;
+
# Language-specific strip/conversion
- $text = $wgContLang->normalizeForSearch( $this->mText );
+ $text = $wgContLang->normalizeForSearch( $text );
+ $lc = SearchEngine::legalSearchChars() . '&#;';
wfProfileIn( __METHOD__ . '-regexps' );
$text = preg_replace( "/<\\/?\\s*[A-Za-z][^>]*?>/",
' ', $wgContLang->lc( " " . $text . " " ) ); # Strip HTML markup
$text = preg_replace( "/(^|\\n)==\\s*([^\\n]+)\\s*==(\\s)/sD",
- "\\1\\2 \\2 \\2\\3", $text ); # Emphasize headings
+ "\\1\\2 \\2 \\2\\3", $text ); # Emphasize headings
# Strip external URLs
$uc = "A-Za-z0-9_\\/:.,~%\\-+&;#?!=()@\\x80-\\xFF";
@@ -92,7 +154,7 @@ class SearchUpdate implements DeferrableUpdate {
$text = preg_replace( $pat2, " \\1 \\3", $text );
$text = preg_replace( "/([^{$lc}])([{$lc}]+)]]([a-z]+)/",
- "\\1\\2 \\2\\3", $text ); # Handle [[game]]s
+ "\\1\\2 \\2\\3", $text ); # Handle [[game]]s
# Strip all remaining non-search characters
$text = preg_replace( "/[^{$lc}]+/", " ", $text );
@@ -118,22 +180,6 @@ class SearchUpdate implements DeferrableUpdate {
# Strip wiki '' and '''
$text = preg_replace( "/''[']*/", " ", $text );
wfProfileOut( __METHOD__ . '-regexps' );
-
- wfRunHooks( 'SearchUpdate', array( $this->mId, $this->mNamespace, $this->mTitle, &$text ) );
-
- # Perform the actual update
- $search->update($this->mId, $search->normalizeText( Title::indexTitle( $this->mNamespace, $this->mTitle ) ),
- $search->normalizeText( $text ) );
-
- wfProfileOut( __METHOD__ );
+ return $text;
}
}
-
-/**
- * Placeholder class
- *
- * @ingroup Search
- */
-class SearchUpdateMyISAM extends SearchUpdate {
- # Inherits everything
-}