** MySQL 5.5.8 or higher
** PostgreSQL 9.2 or higher
** SQLite 3.8.0 or higher
-** Oracle 9.0.1 or higher
-** Microsoft SQL Server 2005 (9.00.1399)
MediaWiki is developed and tested mainly on Unix/Linux platforms, but should
work on Windows as well.
* Database::getProperty(), deprecated in 1.28, has been removed.
* IDatabase::getWikiId(), deprecated in 1.30, has been removed.
Use IDatabase::getDomainID() instead.
+* (T191231) Support for using Oracle or MSSQL as database backends has been
+ dropped.
* …
=== Deprecations in 1.34 ===
support.
MySQL/MariaDB is the recommended DBMS. PostgreSQL or SQLite can also be used,
-but support for them is somewhat less mature. There is experimental support for
-Oracle and Microsoft SQL Server.
+but support for them is somewhat less mature.
The supported versions are:
* MySQL 5.5.8 or later
* PostgreSQL 9.2 or later
* SQLite 3.8.0 or later
-* Oracle 9.0.1 or later
-* Microsoft SQL Server 2005 (9.00.1399)
== Online documentation ==
Documentation for both end-users and site administrators is available on
'SearchHighlighter' => __DIR__ . '/includes/search/SearchHighlighter.php',
'SearchIndexField' => __DIR__ . '/includes/search/SearchIndexField.php',
'SearchIndexFieldDefinition' => __DIR__ . '/includes/search/SearchIndexFieldDefinition.php',
- 'SearchMssql' => __DIR__ . '/includes/search/SearchMssql.php',
'SearchMySQL' => __DIR__ . '/includes/search/SearchMySQL.php',
'SearchNearMatchResultSet' => __DIR__ . '/includes/search/SearchNearMatchResultSet.php',
'SearchNearMatcher' => __DIR__ . '/includes/search/SearchNearMatcher.php',
- 'SearchOracle' => __DIR__ . '/includes/search/SearchOracle.php',
'SearchPostgres' => __DIR__ . '/includes/search/SearchPostgres.php',
'SearchResult' => __DIR__ . '/includes/search/SearchResult.php',
'SearchResultSet' => __DIR__ . '/includes/search/SearchResultSet.php',
// @TODO: clean up grants
// @TODO: auto-include read/editsemiprotected rights?
+$wgGrantPermissions['basic']['autocreateaccount'] = true;
$wgGrantPermissions['basic']['autoconfirmed'] = true;
$wgGrantPermissions['basic']['autopatrol'] = true;
$wgGrantPermissions['basic']['editsemiprotected'] = true;
$blocked = $user->isHidden();
// TODO: remove upon further migration to LinkTarget
- $page = Title::newFromLinkTarget( $page );
+ $title = Title::newFromLinkTarget( $page );
if ( !$blocked ) {
$block = $user->getBlock( $fromReplica );
if ( $block ) {
// Special handling for a user's own talk page. The block is not aware
// of the user, so this must be done here.
- if ( $page->equals( $user->getTalkPage() ) ) {
- $blocked = $block->appliesToUsertalk( $page );
+ if ( $title->equals( $user->getTalkPage() ) ) {
+ $blocked = $block->appliesToUsertalk( $title );
} else {
- $blocked = $block->appliesToTitle( $page );
+ $blocked = $block->appliesToTitle( $title );
}
}
}
// only for the purpose of the hook. We really don't need this here.
$allowUsertalk = $user->isAllowUsertalk();
- Hooks::run( 'UserIsBlockedFrom', [ $user, $page, &$blocked, &$allowUsertalk ] );
+ Hooks::run( 'UserIsBlockedFrom', [ $user, $title, &$blocked, &$allowUsertalk ] );
return $blocked;
}
LinkTarget $page
) {
// TODO: remove when LinkTarget usage will expand further
- $page = Title::newFromLinkTarget( $page );
+ $title = Title::newFromLinkTarget( $page );
// Use getUserPermissionsErrors instead
$result = '';
- if ( !Hooks::run( 'userCan', [ &$page, &$user, $action, &$result ] ) ) {
+ if ( !Hooks::run( 'userCan', [ &$title, &$user, $action, &$result ] ) ) {
return $result ? [] : [ [ 'badaccess-group0' ] ];
}
// Check getUserPermissionsErrors hook
- if ( !Hooks::run( 'getUserPermissionsErrors', [ &$page, &$user, $action, &$result ] ) ) {
+ if ( !Hooks::run( 'getUserPermissionsErrors', [ &$title, &$user, $action, &$result ] ) ) {
$errors = $this->resultToError( $errors, $result );
}
// Check getUserPermissionsErrorsExpensive hook
if (
$rigor !== self::RIGOR_QUICK
&& !( $short && count( $errors ) > 0 )
- && !Hooks::run( 'getUserPermissionsErrorsExpensive', [ &$page, &$user, $action, &$result ] )
+ && !Hooks::run( 'getUserPermissionsErrorsExpensive', [ &$title, &$user, $action, &$result ] )
) {
$errors = $this->resultToError( $errors, $result );
}
LinkTarget $page
) {
// TODO: remove when LinkTarget usage will expand further
- $page = Title::newFromLinkTarget( $page );
+ $title = Title::newFromLinkTarget( $page );
$whitelisted = false;
if ( User::isEveryoneAllowed( 'read' ) ) {
} elseif ( $user->isAllowed( 'read' ) ) {
# If the user is allowed to read pages, he is allowed to read all pages
$whitelisted = true;
- } elseif ( $this->isSameSpecialPage( 'Userlogin', $page )
- || $this->isSameSpecialPage( 'PasswordReset', $page )
- || $this->isSameSpecialPage( 'Userlogout', $page )
+ } elseif ( $this->isSameSpecialPage( 'Userlogin', $title )
+ || $this->isSameSpecialPage( 'PasswordReset', $title )
+ || $this->isSameSpecialPage( 'Userlogout', $title )
) {
# Always grant access to the login page.
# Even anons need to be able to log in.
} elseif ( is_array( $this->whitelistRead ) && count( $this->whitelistRead ) ) {
# Time to check the whitelist
# Only do these checks is there's something to check against
- $name = $page->getPrefixedText();
- $dbName = $page->getPrefixedDBkey();
+ $name = $title->getPrefixedText();
+ $dbName = $title->getPrefixedDBkey();
// Check for explicit whitelisting with and without underscores
if ( in_array( $name, $this->whitelistRead, true )
|| in_array( $dbName, $this->whitelistRead, true ) ) {
$whitelisted = true;
- } elseif ( $page->getNamespace() == NS_MAIN ) {
+ } elseif ( $title->getNamespace() == NS_MAIN ) {
# Old settings might have the title prefixed with
# a colon for main-namespace pages
if ( in_array( ':' . $name, $this->whitelistRead ) ) {
$whitelisted = true;
}
- } elseif ( $page->isSpecialPage() ) {
+ } elseif ( $title->isSpecialPage() ) {
# If it's a special page, ditch the subpage bit and check again
- $name = $page->getDBkey();
+ $name = $title->getDBkey();
list( $name, /* $subpage */ ) =
$this->specialPageFactory->resolveAlias( $name );
if ( $name ) {
if ( !$whitelisted && is_array( $this->whitelistReadRegexp )
&& !empty( $this->whitelistReadRegexp ) ) {
- $name = $page->getPrefixedText();
+ $name = $title->getPrefixedText();
// Check for regex whitelisting
foreach ( $this->whitelistReadRegexp as $listItem ) {
if ( preg_match( $listItem, $name ) ) {
if ( !$whitelisted ) {
# If the title is not whitelisted, give extensions a chance to do so...
- Hooks::run( 'TitleReadWhitelist', [ $page, $user, &$whitelisted ] );
+ Hooks::run( 'TitleReadWhitelist', [ $title, $user, &$whitelisted ] );
if ( !$whitelisted ) {
$errors[] = $this->missingPermissionError( $action, $short );
}
LinkTarget $page
) {
// TODO: remove when LinkTarget usage will expand further
- $page = Title::newFromLinkTarget( $page );
+ $title = Title::newFromLinkTarget( $page );
if ( !Hooks::run( 'TitleQuickPermissions',
- [ $page, $user, $action, &$errors, ( $rigor !== self::RIGOR_QUICK ), $short ] )
+ [ $title, $user, $action, &$errors, ( $rigor !== self::RIGOR_QUICK ), $short ] )
) {
return $errors;
}
- $isSubPage = $this->nsInfo->hasSubpages( $page->getNamespace() ) ?
- strpos( $page->getText(), '/' ) !== false : false;
+ $isSubPage = $this->nsInfo->hasSubpages( $title->getNamespace() ) ?
+ strpos( $title->getText(), '/' ) !== false : false;
if ( $action == 'create' ) {
if (
- ( $this->nsInfo->isTalk( $page->getNamespace() ) &&
+ ( $this->nsInfo->isTalk( $title->getNamespace() ) &&
!$user->isAllowed( 'createtalk' ) ) ||
- ( !$this->nsInfo->isTalk( $page->getNamespace() ) &&
+ ( !$this->nsInfo->isTalk( $title->getNamespace() ) &&
!$user->isAllowed( 'createpage' ) )
) {
$errors[] = $user->isAnon() ? [ 'nocreatetext' ] : [ 'nocreate-loggedin' ];
}
} elseif ( $action == 'move' ) {
if ( !$user->isAllowed( 'move-rootuserpages' )
- && $page->getNamespace() == NS_USER && !$isSubPage ) {
+ && $title->getNamespace() == NS_USER && !$isSubPage ) {
// Show user page-specific message only if the user can move other pages
$errors[] = [ 'cant-move-user-page' ];
}
// Check if user is allowed to move files if it's a file
- if ( $page->getNamespace() == NS_FILE && !$user->isAllowed( 'movefile' ) ) {
+ if ( $title->getNamespace() == NS_FILE && !$user->isAllowed( 'movefile' ) ) {
$errors[] = [ 'movenotallowedfile' ];
}
// Check if user is allowed to move category pages if it's a category page
- if ( $page->getNamespace() == NS_CATEGORY && !$user->isAllowed( 'move-categorypages' ) ) {
+ if ( $title->getNamespace() == NS_CATEGORY && !$user->isAllowed( 'move-categorypages' ) ) {
$errors[] = [ 'cant-move-category-page' ];
}
// User can't move anything
$errors[] = [ 'movenotallowed' ];
} elseif ( !$user->isAllowed( 'move-rootuserpages' )
- && $page->getNamespace() == NS_USER && !$isSubPage ) {
+ && $title->getNamespace() == NS_USER && !$isSubPage ) {
// Show user page-specific message only if the user can move other pages
$errors[] = [ 'cant-move-to-user-page' ];
} elseif ( !$user->isAllowed( 'move-categorypages' )
- && $page->getNamespace() == NS_CATEGORY ) {
+ && $title->getNamespace() == NS_CATEGORY ) {
// Show category page-specific message only if the user can move other pages
$errors[] = [ 'cant-move-to-category-page' ];
}
LinkTarget $page
) {
// TODO: remove & rework upon further use of LinkTarget
- $page = Title::newFromLinkTarget( $page );
- foreach ( $page->getRestrictions( $action ) as $right ) {
+ $title = Title::newFromLinkTarget( $page );
+ foreach ( $title->getRestrictions( $action ) as $right ) {
// Backwards compatibility, rewrite sysop -> editprotected
if ( $right == 'sysop' ) {
$right = 'editprotected';
}
if ( !$user->isAllowed( $right ) ) {
$errors[] = [ 'protectedpagetext', $right, $action ];
- } elseif ( $page->areRestrictionsCascading() && !$user->isAllowed( 'protect' ) ) {
+ } elseif ( $title->areRestrictionsCascading() && !$user->isAllowed( 'protect' ) ) {
$errors[] = [ 'protectedpagetext', 'protect', $action ];
}
}
LinkTarget $page
) {
// TODO: remove & rework upon further use of LinkTarget
- $page = Title::newFromLinkTarget( $page );
- if ( $rigor !== self::RIGOR_QUICK && !$page->isUserConfigPage() ) {
+ $title = Title::newFromLinkTarget( $page );
+ if ( $rigor !== self::RIGOR_QUICK && !$title->isUserConfigPage() ) {
# We /could/ use the protection level on the source page, but it's
# fairly ugly as we have to establish a precedence hierarchy for pages
# included by multiple cascade-protected pages. So just restrict
# it to people with 'protect' permission, as they could remove the
# protection anyway.
- list( $cascadingSources, $restrictions ) = $page->getCascadeProtectionSources();
+ list( $cascadingSources, $restrictions ) = $title->getCascadeProtectionSources();
# Cascading protection depends on more than this page...
# Several cascading protected pages may include this page...
# Check each cascading level
global $wgDeleteRevisionsLimit, $wgLang;
// TODO: remove & rework upon further use of LinkTarget
- $page = Title::newFromLinkTarget( $page );
+ $title = Title::newFromLinkTarget( $page );
if ( $action == 'protect' ) {
- if ( count( $this->getPermissionErrorsInternal( 'edit', $user, $page, $rigor, true ) ) ) {
+ if ( count( $this->getPermissionErrorsInternal( 'edit', $user, $title, $rigor, true ) ) ) {
// If they can't edit, they shouldn't protect.
$errors[] = [ 'protect-cantedit' ];
}
} elseif ( $action == 'create' ) {
- $title_protection = $page->getTitleProtection();
+ $title_protection = $title->getTitleProtection();
if ( $title_protection ) {
if ( $title_protection['permission'] == ''
|| !$user->isAllowed( $title_protection['permission'] )
}
} elseif ( $action == 'move' ) {
// Check for immobile pages
- if ( !$this->nsInfo->isMovable( $page->getNamespace() ) ) {
+ if ( !$this->nsInfo->isMovable( $title->getNamespace() ) ) {
// Specific message for this case
- $errors[] = [ 'immobile-source-namespace', $page->getNsText() ];
- } elseif ( !$page->isMovable() ) {
+ $errors[] = [ 'immobile-source-namespace', $title->getNsText() ];
+ } elseif ( !$title->isMovable() ) {
// Less specific message for rarer cases
$errors[] = [ 'immobile-source-page' ];
}
} elseif ( $action == 'move-target' ) {
- if ( !$this->nsInfo->isMovable( $page->getNamespace() ) ) {
- $errors[] = [ 'immobile-target-namespace', $page->getNsText() ];
- } elseif ( !$page->isMovable() ) {
+ if ( !$this->nsInfo->isMovable( $title->getNamespace() ) ) {
+ $errors[] = [ 'immobile-target-namespace', $title->getNsText() ];
+ } elseif ( !$title->isMovable() ) {
$errors[] = [ 'immobile-target-page' ];
}
} elseif ( $action == 'delete' ) {
- $tempErrors = $this->checkPageRestrictions( 'edit', $user, [], $rigor, true, $page );
+ $tempErrors = $this->checkPageRestrictions( 'edit', $user, [], $rigor, true, $title );
if ( !$tempErrors ) {
$tempErrors = $this->checkCascadingSourcesRestrictions( 'edit',
- $user, $tempErrors, $rigor, true, $page );
+ $user, $tempErrors, $rigor, true, $title );
}
if ( $tempErrors ) {
// If protection keeps them from editing, they shouldn't be able to delete.
$errors[] = [ 'deleteprotected' ];
}
if ( $rigor !== self::RIGOR_QUICK && $wgDeleteRevisionsLimit
- && !$this->userCan( 'bigdelete', $user, $page ) && $page->isBigDeletion()
+ && !$this->userCan( 'bigdelete', $user, $title ) && $title->isBigDeletion()
) {
$errors[] = [ 'delete-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ];
}
} elseif ( $action === 'undelete' ) {
- if ( count( $this->getPermissionErrorsInternal( 'edit', $user, $page, $rigor, true ) ) ) {
+ if ( count( $this->getPermissionErrorsInternal( 'edit', $user, $title, $rigor, true ) ) ) {
// Undeleting implies editing
$errors[] = [ 'undelete-cantedit' ];
}
- if ( !$page->exists()
- && count( $this->getPermissionErrorsInternal( 'create', $user, $page, $rigor, true ) )
+ if ( !$title->exists()
+ && count( $this->getPermissionErrorsInternal( 'create', $user, $title, $rigor, true ) )
) {
// Undeleting where nothing currently exists implies creating
$errors[] = [ 'undelete-cantcreate' ];
LinkTarget $page
) {
// TODO: remove & rework upon further use of LinkTarget
- $page = Title::newFromLinkTarget( $page );
+ $title = Title::newFromLinkTarget( $page );
# Only 'createaccount' can be performed on special pages,
# which don't actually exist in the DB.
- if ( $page->getNamespace() == NS_SPECIAL && $action !== 'createaccount' ) {
+ if ( $title->getNamespace() == NS_SPECIAL && $action !== 'createaccount' ) {
$errors[] = [ 'ns-specialprotected' ];
}
# Check $wgNamespaceProtection for restricted namespaces
- if ( $page->isNamespaceProtected( $user ) ) {
- $ns = $page->getNamespace() == NS_MAIN ?
- wfMessage( 'nstab-main' )->text() : $page->getNsText();
- $errors[] = $page->getNamespace() == NS_MEDIAWIKI ?
+ if ( $title->isNamespaceProtected( $user ) ) {
+ $ns = $title->getNamespace() == NS_MAIN ?
+ wfMessage( 'nstab-main' )->text() : $title->getNsText();
+ $errors[] = $title->getNamespace() == NS_MEDIAWIKI ?
[ 'protectedinterface', $action ] : [ 'namespaceprotected', $ns, $action ];
}
LinkTarget $page
) {
// TODO: remove & rework upon further use of LinkTarget
- $page = Title::newFromLinkTarget( $page );
+ $title = Title::newFromLinkTarget( $page );
if ( $action != 'patrol' ) {
$error = null;
// Sitewide CSS/JSON/JS changes, like all NS_MEDIAWIKI changes, also require the
// editinterface right. That's implemented as a restriction so no check needed here.
- if ( $page->isSiteCssConfigPage() && !$user->isAllowed( 'editsitecss' ) ) {
+ if ( $title->isSiteCssConfigPage() && !$user->isAllowed( 'editsitecss' ) ) {
$error = [ 'sitecssprotected', $action ];
- } elseif ( $page->isSiteJsonConfigPage() && !$user->isAllowed( 'editsitejson' ) ) {
+ } elseif ( $title->isSiteJsonConfigPage() && !$user->isAllowed( 'editsitejson' ) ) {
$error = [ 'sitejsonprotected', $action ];
- } elseif ( $page->isSiteJsConfigPage() && !$user->isAllowed( 'editsitejs' ) ) {
+ } elseif ( $title->isSiteJsConfigPage() && !$user->isAllowed( 'editsitejs' ) ) {
$error = [ 'sitejsprotected', $action ];
- } elseif ( $page->isRawHtmlMessage() ) {
+ } elseif ( $title->isRawHtmlMessage() ) {
// Raw HTML can be used to deploy CSS or JS so require rights for both.
if ( !$user->isAllowed( 'editsitejs' ) ) {
$error = [ 'sitejsprotected', $action ];
LinkTarget $page
) {
// TODO: remove & rework upon further use of LinkTarget
- $page = Title::newFromLinkTarget( $page );
+ $title = Title::newFromLinkTarget( $page );
# Protect css/json/js subpages of user pages
# XXX: this might be better using restrictions
return $errors;
}
- if ( preg_match( '/^' . preg_quote( $user->getName(), '/' ) . '\//', $page->getText() ) ) {
+ if ( preg_match( '/^' . preg_quote( $user->getName(), '/' ) . '\//', $title->getText() ) ) {
// Users need editmyuser* to edit their own CSS/JSON/JS subpages.
if (
- $page->isUserCssConfigPage()
+ $title->isUserCssConfigPage()
&& !$user->isAllowedAny( 'editmyusercss', 'editusercss' )
) {
$errors[] = [ 'mycustomcssprotected', $action ];
} elseif (
- $page->isUserJsonConfigPage()
+ $title->isUserJsonConfigPage()
&& !$user->isAllowedAny( 'editmyuserjson', 'edituserjson' )
) {
$errors[] = [ 'mycustomjsonprotected', $action ];
} elseif (
- $page->isUserJsConfigPage()
+ $title->isUserJsConfigPage()
&& !$user->isAllowedAny( 'editmyuserjs', 'edituserjs' )
) {
$errors[] = [ 'mycustomjsprotected', $action ];
} elseif (
- $page->isUserJsConfigPage()
+ $title->isUserJsConfigPage()
&& !$user->isAllowedAny( 'edituserjs', 'editmyuserjsredirect' )
) {
// T207750 - do not allow users to edit a redirect if they couldn't edit the target
- $rev = $this->revisionLookup->getRevisionByTitle( $page );
+ $rev = $this->revisionLookup->getRevisionByTitle( $title );
$content = $rev ? $rev->getContent( 'main', RevisionRecord::RAW ) : null;
$target = $content ? $content->getUltimateRedirectTarget() : null;
if ( $target && (
// and only very highly privileged users could remove it.
if ( !in_array( $action, [ 'delete', 'deleterevision', 'suppressrevision' ], true ) ) {
if (
- $page->isUserCssConfigPage()
+ $title->isUserCssConfigPage()
&& !$user->isAllowed( 'editusercss' )
) {
$errors[] = [ 'customcssprotected', $action ];
} elseif (
- $page->isUserJsonConfigPage()
+ $title->isUserJsonConfigPage()
&& !$user->isAllowed( 'edituserjson' )
) {
$errors[] = [ 'customjsonprotected', $action ];
} elseif (
- $page->isUserJsConfigPage()
+ $title->isUserJsConfigPage()
&& !$user->isAllowed( 'edituserjs' )
) {
$errors[] = [ 'customjsprotected', $action ];
// Postgres: Temp tables are automatically deleted upon end of session
// Same Temp table name hides existing table for current session
- if ( $this->dropCurrentTables
- && !in_array( $this->db->getType(), [ 'oracle' ] )
- ) {
+ if ( $this->dropCurrentTables ) {
if ( $oldTableName === $newTableName ) {
// Last ditch check to avoid data loss
throw new LogicException( "Not dropping new table, as '$newTableName'"
* @return string
*/
public function getReadableName() {
- // Messages: config-type-mysql, config-type-postgres, config-type-sqlite,
- // config-type-oracle
+ // Messages: config-type-mysql, config-type-postgres, config-type-sqlite
return wfMessage( 'config-type-' . $this->getName() )->text();
}
$allNames = [];
- // Messages: config-type-mysql, config-type-postgres, config-type-oracle,
- // config-type-sqlite
+ // Messages: config-type-mysql, config-type-postgres, config-type-sqlite
foreach ( self::getDBTypes() as $name ) {
$allNames[] = wfMessage( "config-type-$name" )->text();
}
$settings = '';
$defaultType = $this->getVar( 'wgDBtype' );
- // Messages: config-dbsupport-mysql, config-dbsupport-postgres, config-dbsupport-oracle,
- // config-dbsupport-sqlite, config-dbsupport-mssql
+ // Messages: config-dbsupport-mysql, config-dbsupport-postgres, config-dbsupport-sqlite
$dbSupport = '';
foreach ( Installer::getDBTypes() as $type ) {
$dbSupport .= wfMessage( "config-dbsupport-$type" )->plain() . "\n";
) .
"</li>\n";
- // Messages: config-header-mysql, config-header-postgres, config-header-oracle,
- // config-header-sqlite
+ // Messages: config-header-mysql, config-header-postgres, config-header-sqlite
$settings .= Html::openElement(
'div',
[
"config-db-type": "Database type:",
"config-db-host": "Database host:",
"config-db-host-help": "If your database server is on a different server, enter the host name or IP address here.\n\nIf you are using shared web hosting, your hosting provider should give you the correct host name in their documentation.\n\nIf you are using MySQL, using \"localhost\" may not work for the server name. If it does not, try \"127.0.0.1\" for the local IP address.\n\nIf you are using PostgreSQL, leave this field blank to connect via a Unix socket.",
- "config-db-host-oracle": "Database TNS:",
- "config-db-host-oracle-help": "Enter a valid [http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm Local Connect Name]; a tnsnames.ora file must be visible to this installation.<br />If you are using client libraries 10g or newer you can also use the [http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm Easy Connect] naming method.",
"config-db-wiki-settings": "Identify this wiki",
"config-db-name": "Database name (no hyphens):",
"config-db-name-help": "Choose a name that identifies your wiki.\nIt should not contain spaces.\n\nIf you are using shared web hosting, your hosting provider will either give you a specific database name to use or let you create databases via a control panel.",
- "config-db-name-oracle": "Database schema:",
- "config-db-account-oracle-warn": "There are three supported scenarios for installing Oracle as database backend:\n\nIf you wish to create database account as part of the installation process, please supply an account with SYSDBA role as database account for installation and specify the desired credentials for the web-access account, otherwise you can either create the web-access account manually and supply only that account (if it has required permissions to create the schema objects) or supply two different accounts, one with create privileges and a restricted one for web access.\n\nScript for creating an account with required privileges can be found in \"maintenance/oracle/\" directory of this installation. Keep in mind that using a restricted account will disable all maintenance capabilities with the default account.",
"config-db-install-account": "User account for installation",
"config-db-username": "Database username:",
"config-db-password": "Database password:",
"config-pg-test-error": "Cannot connect to database <strong>$1</strong>: $2",
"config-sqlite-dir": "SQLite data directory:",
"config-sqlite-dir-help": "SQLite stores all data in a single file.\n\nThe directory you provide must be writable by the webserver during installation.\n\nIt should <strong>not</strong> be accessible via the web; this is why we're not putting it where your PHP files are.\n\nThe installer will write a <code>.htaccess</code> file along with it, but if that fails someone can gain access to your raw database.\nThat includes raw user data (email addresses, hashed passwords) as well as deleted revisions and other restricted data on the wiki.\n\nConsider putting the database somewhere else altogether, for example in <code>/var/lib/mediawiki/yourwiki</code>.",
- "config-oracle-def-ts": "Default tablespace:",
- "config-oracle-temp-ts": "Temporary tablespace:",
"config-type-mysql": "MariaDB, MySQL, or compatible",
"config-type-postgres": "PostgreSQL",
"config-type-sqlite": "SQLite",
- "config-type-oracle": "Oracle",
- "config-type-mssql": "Microsoft SQL Server",
"config-support-info": "MediaWiki supports the following database systems:\n\n$1\n\nIf you do not see the database system you are trying to use listed below, then follow the instructions linked above to enable support.",
"config-dbsupport-mysql": "* [{{int:version-db-mariadb-url}} MariaDB] is the primary target for MediaWiki and is best supported. MediaWiki also works with [{{int:version-db-mysql-url}} MySQL] and [{{int:version-db-percona-url}} Percona Server], which are MariaDB compatible. ([https://www.php.net/manual/en/mysqli.installation.php How to compile PHP with MySQL support])",
"config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] is a popular open source database system as an alternative to MySQL. ([https://www.php.net/manual/en/pgsql.installation.php How to compile PHP with PostgreSQL support])",
"config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] is a lightweight database system that is very well supported. ([https://www.php.net/manual/en/pdo.installation.php How to compile PHP with SQLite support], uses PDO)",
- "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] is a commercial enterprise database. ([https://www.php.net/manual/en/oci8.installation.php How to compile PHP with OCI8 support])",
- "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] is a commercial enterprise database for Windows. ([https://www.php.net/manual/en/sqlsrv.installation.php How to compile PHP with SQLSRV support])",
"config-header-mysql": "MariaDB/MySQL settings",
"config-header-postgres": "PostgreSQL settings",
"config-header-sqlite": "SQLite settings",
- "config-header-oracle": "Oracle settings",
- "config-header-mssql": "Microsoft SQL Server settings",
"config-invalid-db-type": "Invalid database type.",
"config-missing-db-name": "You must enter a value for \"{{int:config-db-name}}\".",
"config-missing-db-host": "You must enter a value for \"{{int:config-db-host}}\".",
- "config-missing-db-server-oracle": "You must enter a value for \"{{int:config-db-host-oracle}}\".",
- "config-invalid-db-server-oracle": "Invalid database TNS \"$1\".\nUse either \"TNS Name\" or an \"Easy Connect\" string ([http://docs.oracle.com/cd/E11882_01/network.112/e10836/naming.htm Oracle Naming Methods]).",
"config-invalid-db-name": "Invalid database name \"$1\".\nUse only ASCII letters (a-z, A-Z), numbers (0-9), underscores (_) and hyphens (-).",
"config-invalid-db-prefix": "Invalid database prefix \"$1\".\nUse only ASCII letters (a-z, A-Z), numbers (0-9), underscores (_) and hyphens (-).",
"config-connection-error": "$1.\n\nCheck the host, username and password and try again. If using \"localhost\" as the database host, try using \"127.0.0.1\" instead (or vice versa).",
"config-invalid-schema": "Invalid schema for MediaWiki \"$1\".\nUse only ASCII letters (a-z, A-Z), numbers (0-9) and underscores (_).",
- "config-db-sys-create-oracle": "Installer only supports using a SYSDBA account for creating a new account.",
- "config-db-sys-user-exists-oracle": "User account \"$1\" already exists. SYSDBA can only be used for creating of a new account!",
"config-postgres-old": "PostgreSQL $1 or later is required. You have $2.",
- "config-mssql-old": "Microsoft SQL Server $1 or later is required. You have $2.",
"config-sqlite-name-help": "Choose a name that identifies your wiki.\nDo not use spaces or hyphens.\nThis will be used for the SQLite data filename.",
"config-sqlite-parent-unwritable-group": "Cannot create the data directory <code><nowiki>$1</nowiki></code>, because the parent directory <code><nowiki>$2</nowiki></code> is not writable by the webserver.\n\nThe installer has determined the user your webserver is running as.\nMake the <code><nowiki>$3</nowiki></code> directory writable by it to continue.\nOn a Unix/Linux system do:\n\n<pre>cd $2\nmkdir $3\nchgrp $4 $3\nchmod g+w $3</pre>",
"config-sqlite-parent-unwritable-nogroup": "Cannot create the data directory <code><nowiki>$1</nowiki></code>, because the parent directory <code><nowiki>$2</nowiki></code> is not writable by the webserver.\n\nThe installer could not determine the user your webserver is running as.\nMake the <code><nowiki>$3</nowiki></code> directory globally writable by it (and others!) to continue.\nOn a Unix/Linux system do:\n\n<pre>cd $2\nmkdir $3\nchmod a+w $3</pre>",
"config-mysql-engine": "Storage engine:",
"config-mysql-innodb": "InnoDB (recommended)",
"config-mysql-engine-help": "<strong>InnoDB</strong> is almost always the best option, since it has good concurrency support.\n\n<strong>MyISAM</strong> may be faster in single-user or read-only installations.\nMyISAM databases tend to get corrupted more often than InnoDB databases.",
- "config-mssql-auth": "Authentication type:",
- "config-mssql-install-auth": "Select the authentication type that will be used to connect to the database during the installation process.\nIf you select \"{{int:config-mssql-windowsauth}}\", the credentials of whatever user the webserver is running as will be used.",
- "config-mssql-web-auth": "Select the authentication type that the web server will use to connect to the database server, during ordinary operation of the wiki.\nIf you select \"{{int:config-mssql-windowsauth}}\", the credentials of whatever user the webserver is running as will be used.",
- "config-mssql-sqlauth": "SQL Server Authentication",
- "config-mssql-windowsauth": "Windows Authentication",
"config-site-name": "Name of wiki:",
"config-site-name-help": "This will appear in the title bar of the browser and in various other places.",
"config-site-name-blank": "Enter a site name.",
"config-db-type": "Field label in the MediaWiki installer followed by possible database types.",
"config-db-host": "Used as label.\n\nAlso used in {{msg-mw|Config-missing-db-host}}.",
"config-db-host-help": "{{doc-singularthey}}",
- "config-db-host-oracle": "TNS = [[w:Transparent Network Substrate]].\n\nUsed as label.\n\nAlso used in {{msg-mw|Config-missing-db-server-oracle}}.",
- "config-db-host-oracle-help": "See also:\n* {{msg-mw|Config-invalid-db-server-oracle}}",
"config-db-wiki-settings": "This is more acurate: \"Enter identifying or distinguishing data for this wiki\" since a MySQL database can host tables of several wikis.",
"config-db-name": "Used as label.\n\nAlso used in {{msg-mw|Config-missing-db-name}}.\n{{Identical|Database name}}",
"config-db-name-help": "Help box text in the MediaWiki installer.",
- "config-db-name-oracle": "Field label in the MediaWiki installer where an Oracle database schema can be specified.",
- "config-db-account-oracle-warn": "A \"[[:wikipedia:Front and back ends|backend]]\" is a system or component that ordinary users don't interact with directly and don't need to know about, and that is responsible for a distinct task or service - for example, a storage back-end is a generic system for storing data which other applications can use. Possible alternatives for back-end are \"system\" or \"service\", or (depending on context and language) even leave it untranslated.",
"config-db-install-account": "Legend in the MediaWiki installer for the section where database username and password have to be provided.",
"config-db-username": "Used as label.",
"config-db-password": "Field label in the MediaWiki installer where database password has to be provided.",
"config-pg-test-error": "Parameters:\n* $1 - database name\n* $2 - error message",
"config-sqlite-dir": "Field label for a folder location.",
"config-sqlite-dir-help": "{{doc-important|Do not translate <code>.htaccess</code> and <code>/var/lib/mediawiki/yourwiki</code>.}}\nUsed in help box.",
- "config-oracle-def-ts": "Field label for an Oracle default tablespace.",
- "config-oracle-temp-ts": "Field label for an Oracle temporary tablespace.",
"config-type-mysql": "\"Or compatible\" refers to several database systems that are compatible with MySQL, as explained in {{msg-mw|config-dbsupport-mysql}}, and thus also work with this choice of database type.",
"config-type-postgres": "{{optional}}",
"config-type-sqlite": "{{optional}}",
- "config-type-oracle": "{{optional}}",
- "config-type-mssql": "{{optional}}",
- "config-support-info": "Parameters:\n* $1 - a list of DBMSs that MediaWiki supports, composed with config-dbsupport-* messages.\nSee also:\n* {{msg-mw|Config-dbsupport-mysql}}\n* {{msg-mw|Config-dbsupport-postgres}}\n* {{msg-mw|Config-dbsupport-oracle}}\n* {{msg-mw|Config-dbsupport-sqlite}}\n* {{msg-mw|Config-dbsupport-mssql}}",
+ "config-support-info": "Parameters:\n* $1 - a list of DBMSs that MediaWiki supports, composed with config-dbsupport-* messages.\nSee also:\n* {{msg-mw|Config-dbsupport-mysql}}\n* {{msg-mw|Config-dbsupport-postgres}}\n* {{msg-mw|Config-dbsupport-sqlite}}",
"config-dbsupport-mysql": "Used in:\n* {{msg-mw|config-support-info}}\n{{Related|Config-dbsupport}}",
"config-dbsupport-postgres": "Used in:\n* {{msg-mw|config-support-info}}\n{{Related|Config-dbsupport}}",
"config-dbsupport-sqlite": "Used in:\n* {{msg-mw|config-support-info}}\n{{Related|Config-dbsupport}}",
- "config-dbsupport-oracle": "Used in:\n* {{msg-mw|Config-support-info}}.\n{{Related|Config-dbsupport}}",
- "config-dbsupport-mssql": "Used in:\n* {{msg-mw|Config-support-info}}\n{{Related|Config-dbsupport}}",
"config-header-mysql": "Header for MySQL database settings in the MediaWiki installer.",
"config-header-postgres": "Header for PostgreSQL database settings in the MediaWiki installer.",
"config-header-sqlite": "Header for SQLite database settings in the MediaWiki installer.",
- "config-header-oracle": "Header for Oracle database settings in the MediaWiki installer.",
- "config-header-mssql": "Used as a section heading on the installer form, inside of a fieldset",
"config-invalid-db-type": "Error message in MediaWiki installer when an invalid database type has been provided.",
"config-missing-db-name": "Refers to {{msg-mw|Config-db-name}}.\n{{Related|Config-missing}}",
"config-missing-db-host": "Refers to {{msg-mw|Config-db-host}}.\n{{Related|Config-missing}}",
- "config-missing-db-server-oracle": "Refers to {{msg-mw|Config-db-host-oracle}}.\n{{Related|Config-missing}}",
- "config-invalid-db-server-oracle": "Used as error message. Parameters:\n* $1 - database server name\nSee also:\n* {{msg-mw|Config-db-host-oracle-help}}",
"config-invalid-db-name": "Used as error message. Parameters:\n* $1 - database name\nSee also:\n* {{msg-mw|Config-invalid-db-prefix}}",
"config-invalid-db-prefix": "Used as error message. Parameters:\n* $1 - database prefix\nSee also:\n* {{msg-mw|Config-invalid-db-name}}",
"config-connection-error": "$1 is the external error from the database, such as \"DB connection error: Access denied for user 'dba'@'localhost' (using password: YES) (localhost).\"\n\nIf you're translating this message to a right-to-left language, consider writing <nowiki><div dir=\"ltr\">$1.</div></nowiki>. (When the bidi features for HTML5 will be implemented in the browsers, it will probably be a good idea to write it as <nowiki><div dir=\"auto\">$1.</div></nowiki>.)",
"config-invalid-schema": "*$1 - schema name",
- "config-db-sys-create-oracle": "Error message in the MediaWiki installer when Oracle is used as database and an incorrect user account type has been provided.",
- "config-db-sys-user-exists-oracle": "Used as error message. Parameters:\n* $1 - database username",
"config-postgres-old": "Used as error message. Used as warning. Parameters:\n* $1 - minimum version\n* $2 - the version of PostgreSQL that has been installed\n{{Related|Config-old}}",
- "config-mssql-old": "Used as an error message. Parameters:\n* $1 - minimum version\n* $2 - the version of Microsoft SQL Server that has been installed\n{{Related|Config-old}}",
"config-sqlite-name-help": "Help text for the form field for the SQLite data file name.",
"config-sqlite-parent-unwritable-group": "Used as SQLite error message. Parameters:\n* $1 - data directory\n* $2 - \"dirname\" part of $1\n* $3 - \"basename\" part of $1\n* $4 - web server's primary group name\nSee also:\n* {{msg-mw|Config-sqlite-parent-unwritable-nogroup}}",
"config-sqlite-parent-unwritable-nogroup": "Used as SQLite error message. Parameters:\n* $1 - data directory\n* $2 - \"dirname\" part of $1\n* $3 - \"basename\" part of $1\nSee also:\n* {{msg-mw|Config-sqlite-parent-unwritable-group}}",
"config-mysql-engine": "Field label for MySQL storage engine in the MediaWiki installer.",
"config-mysql-innodb": "Option for the MySQL storage engine in the MediaWiki installer.",
"config-mysql-engine-help": "Help text in MediaWiki installer with advice for picking a MySQL storage engine.",
- "config-mssql-auth": "Radio button group label.\n\nFollowed by the following radio button labels:\n* {{msg-mw|Config-mssql-sqlauth}}\n* {{msg-mw|Config-mssql-windowsauth}}",
- "config-mssql-install-auth": "Used as the help text for the \"Authentication type\" radio button when typing in database settings for installation.\n\nRefers to {{msg-mw|Config-mssql-windowsauth}}.\n\nSee also:\n* {{msg-mw|Config-mssql-web-auth}}",
- "config-mssql-web-auth": "Used as the help text for the \"Authentication type\" radio button when typing in database settings for normal wiki usage.\n\nRefers to {{msg-mw|Config-mssql-windowsauth}}.\n\nSee also:\n* {{msg-mw|Config-mssql-install-auth}}",
- "config-mssql-sqlauth": "Radio button.\n\n\"SQL Server\" refers to \"Microsoft SQL Server\".\n\nSee also:\n* {{msg-mw|Config-mssql-windowsauth}}",
- "config-mssql-windowsauth": "Radio button. The official term is \"Integrated Windows Authentication\" but Microsoft itself uses \"Windows Authentication\" elsewhere in Microsoft SQL Server as a synonym.\n\nAlso used in:\n* {{msg-mw|Config-mssql-install-auth}}\n* {{msg-mw|Config-mssql-web-auth}}\n\nSee also:\n* {{msg-mw|Config-mssql-sqlauth}}",
"config-site-name": "Field label for the form field where a wiki name has to be entered.",
"config-site-name-help": "Help text for the form field where a wiki name has to be entered.",
"config-site-name-blank": "Error text in the MediaWiki installer when the site name is left empty.",
return SearchMySQL::class;
case 'postgres':
return SearchPostgres::class;
- case 'mssql':
- return SearchMssql::class;
- case 'oracle':
- return SearchOracle::class;
default:
return SearchEngineDummy::class;
}
+++ /dev/null
-<?php
-/**
- * Mssql search engine
- *
- * 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
- */
-
-use MediaWiki\MediaWikiServices;
-use Wikimedia\Rdbms\IResultWrapper;
-
-/**
- * Search engine hook base class for Mssql (ConText).
- * @ingroup Search
- */
-class SearchMssql extends SearchDatabase {
- /**
- * Perform a full text search query and return a result set.
- *
- * @param string $term Raw search term
- * @return SqlSearchResultSet|null
- */
- protected function doSearchTextInDB( $term ) {
- $dbr = $this->lb->getConnectionRef( DB_REPLICA );
- $resultSet = $dbr->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 string $term Raw search term
- * @return SqlSearchResultSet|null
- */
- protected function doSearchTitleInDB( $term ) {
- $dbr = $this->lb->getConnectionRef( DB_REPLICA );
- $resultSet = $dbr->query( $this->getQuery( $this->filter( $term ), false ) );
-
- return new SqlSearchResultSet( $resultSet, $this->searchTerms );
- }
-
- /**
- * Return a partial WHERE clause to limit the search to the given namespaces
- *
- * @return string
- */
- private function queryNamespaces() {
- $namespaces = implode( ',', $this->namespaces );
- if ( $namespaces == '' ) {
- $namespaces = '0';
- }
- return 'AND page_namespace IN (' . $namespaces . ')';
- }
-
- /**
- * Return a LIMIT clause to limit results on the query.
- *
- * @param string $sql
- *
- * @return string
- */
- private function queryLimit( $sql ) {
- $dbr = $this->lb->getConnectionRef( DB_REPLICA );
-
- return $dbr->limitResult( $sql, $this->limit, $this->offset );
- }
-
- /**
- * Does not do anything for generic search engine
- * subclasses may define this though
- *
- * @param string $filteredTerm
- * @param bool $fulltext
- * @return string
- */
- function queryRanking( $filteredTerm, $fulltext ) {
- return ' ORDER BY ftindex.[RANK] DESC'; // return ' ORDER BY score(1)';
- }
-
- /**
- * Construct the full SQL query to do the search.
- * The guts shoulds be constructed in queryMain()
- *
- * @param string $filteredTerm
- * @param bool $fulltext
- * @return string
- */
- private function getQuery( $filteredTerm, $fulltext ) {
- return $this->queryLimit( $this->queryMain( $filteredTerm, $fulltext ) . ' ' .
- $this->queryNamespaces() . ' ' .
- $this->queryRanking( $filteredTerm, $fulltext ) . ' ' );
- }
-
- /**
- * Picks which field to index on, depending on what type of query.
- *
- * @param bool $fulltext
- * @return string
- */
- function getIndexField( $fulltext ) {
- return $fulltext ? 'si_text' : 'si_title';
- }
-
- /**
- * Get the base part of the search query.
- *
- * @param string $filteredTerm
- * @param bool $fulltext
- * @return string
- */
- private function queryMain( $filteredTerm, $fulltext ) {
- $match = $this->parseQuery( $filteredTerm, $fulltext );
- $dbr = $this->lb->getMaintenanceConnectionRef( DB_REPLICA );
- $page = $dbr->tableName( 'page' );
- $searchindex = $dbr->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] ';
- }
-
- /** @todo document
- * @param string $filteredText
- * @param bool $fulltext
- * @return string
- */
- private function parseQuery( $filteredText, $fulltext ) {
- $lc = $this->legalSearchChars( self::CHARS_NO_SYNTAX );
- $this->searchTerms = [];
-
- # @todo FIXME: This doesn't handle parenthetical expressions.
- $m = [];
- $q = [];
-
- if ( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
- $filteredText, $m, PREG_SET_ORDER ) ) {
- foreach ( $m as $terms ) {
- $q[] = $terms[1] . MediaWikiServices::getInstance()->getContentLanguage()->
- 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;
- }
- }
-
- $dbr = $this->lb->getConnectionRef( DB_REPLICA );
- $searchon = $dbr->addQuotes( implode( ',', $q ) );
- $field = $this->getIndexField( $fulltext );
-
- return "$field, $searchon";
- }
-
- /**
- * Create or update the search index record for the given page.
- * Title and text should be pre-processed.
- *
- * @param int $id
- * @param string $title
- * @param string $text
- * @return bool|IResultWrapper
- */
- 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
- // 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
- $dbr = $this->lb->getMaintenanceConnectionRef( DB_MASTER );
- $table = $dbr->tableName( 'searchindex' );
- $utf8bom = '0xEFBBBF';
- $si_title = $utf8bom . bin2hex( $title );
- $si_text = $utf8bom . bin2hex( $text );
- $sql = "DELETE FROM $table WHERE si_page = $id;";
- $sql .= "INSERT INTO $table (si_page, si_title, si_text) VALUES ($id, $si_title, $si_text)";
- return $dbr->query( $sql, 'SearchMssql::update' );
- }
-
- /**
- * Update a search index record's title only.
- * Title should be pre-processed.
- *
- * @param int $id
- * @param string $title
- * @return bool|IResultWrapper
- */
- function updateTitle( $id, $title ) {
- $dbr = $this->lb->getMaintenanceConnectionRef( DB_MASTER );
- $table = $dbr->tableName( 'searchindex' );
-
- // see update for why we are using the utf8bom
- $utf8bom = '0xEFBBBF';
- $si_title = $utf8bom . bin2hex( $title );
- $sql = "DELETE FROM $table WHERE si_page = $id;";
- $sql .= "INSERT INTO $table (si_page, si_title, si_text) VALUES ($id, $si_title, 0x00)";
- return $dbr->query( $sql, 'SearchMssql::updateTitle' );
- }
-}
+++ /dev/null
-<?php
-/**
- * Oracle search engine
- *
- * Copyright © 2004 Brion Vibber <brion@pobox.com>
- * https://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
- */
-
-use MediaWiki\MediaWikiServices;
-
-/**
- * Search engine hook base class for Oracle (ConText).
- * @ingroup Search
- */
-class SearchOracle extends SearchDatabase {
- private $reservedWords = [
- '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,
- ];
-
- /**
- * Perform a full text search query and return a result set.
- *
- * @param string $term Raw search term
- * @return SqlSearchResultSet|null
- */
- protected function doSearchTextInDB( $term ) {
- if ( $term == '' ) {
- return null;
- }
-
- $dbr = $this->lb->getConnectionRef( DB_REPLICA );
- $resultSet = $dbr->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 string $term Raw search term
- * @return SqlSearchResultSet|null
- */
- protected function doSearchTitleInDB( $term ) {
- if ( $term == '' ) {
- return null;
- }
-
- $dbr = $this->lb->getConnectionRef( DB_REPLICA );
- $resultSet = $dbr->query( $this->getQuery( $this->filter( $term ), false ) );
- return new SqlSearchResultSet( $resultSet, $this->searchTerms );
- }
-
- /**
- * Return a partial WHERE clause to limit the search to the given namespaces
- * @return string
- */
- private function queryNamespaces() {
- if ( is_null( $this->namespaces ) ) {
- return '';
- }
- if ( $this->namespaces === [] ) {
- $namespaces = '0';
- } else {
- $dbr = $this->lb->getConnectionRef( DB_REPLICA );
- $namespaces = $dbr->makeList( $this->namespaces );
- }
- return 'AND page_namespace IN (' . $namespaces . ')';
- }
-
- /**
- * Return a LIMIT clause to limit results on the query.
- *
- * @param string $sql
- *
- * @return string
- */
- private function queryLimit( $sql ) {
- $dbr = $this->lb->getConnectionRef( DB_REPLICA );
-
- return $dbr->limitResult( $sql, $this->limit, $this->offset );
- }
-
- /**
- * Does not do anything for generic search engine
- * subclasses may define this though
- *
- * @param string $filteredTerm
- * @param bool $fulltext
- * @return string
- */
- function queryRanking( $filteredTerm, $fulltext ) {
- return ' ORDER BY score(1)';
- }
-
- /**
- * Construct the full SQL query to do the search.
- * The guts shoulds be constructed in queryMain()
- * @param string $filteredTerm
- * @param bool $fulltext
- * @return string
- */
- private function getQuery( $filteredTerm, $fulltext ) {
- return $this->queryLimit( $this->queryMain( $filteredTerm, $fulltext ) . ' ' .
- $this->queryNamespaces() . ' ' .
- $this->queryRanking( $filteredTerm, $fulltext ) . ' ' );
- }
-
- /**
- * Picks which field to index on, depending on what type of query.
- * @param bool $fulltext
- * @return string
- */
- private function getIndexField( $fulltext ) {
- return $fulltext ? 'si_text' : 'si_title';
- }
-
- /**
- * Get the base part of the search query.
- *
- * @param string $filteredTerm
- * @param bool $fulltext
- * @return string
- */
- function queryMain( $filteredTerm, $fulltext ) {
- $match = $this->parseQuery( $filteredTerm, $fulltext );
-
- $dbr = $this->lb->getMaintenanceConnectionRef( DB_REPLICA );
- $page = $dbr->tableName( 'page' );
- $searchindex = $dbr->tableName( 'searchindex' );
-
- return 'SELECT page_id, page_namespace, page_title ' .
- "FROM $page,$searchindex " .
- 'WHERE page_id=si_page AND ' . $match;
- }
-
- /**
- * Parse a user input search string, and return an SQL fragment to be used
- * as part of a WHERE clause
- * @param string $filteredText
- * @param bool $fulltext
- * @return string
- */
- private function parseQuery( $filteredText, $fulltext ) {
- $lc = $this->legalSearchChars( self::CHARS_NO_SYNTAX );
- $this->searchTerms = [];
-
- # @todo FIXME: This doesn't handle parenthetical expressions.
- $m = [];
- $searchon = '';
- 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 = MediaWikiServices::getInstance()->getContentLanguage()->
- 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 );
- }
- } else {
- $searchon .= ( $terms[1] == '-' ? ' ~' : ' & ' ) . $this->escapeTerm( $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;
- }
- }
-
- $dbr = $this->lb->getConnectionRef( DB_REPLICA );
- $searchon = $dbr->addQuotes( ltrim( $searchon, ' &' ) );
- $field = $this->getIndexField( $fulltext );
-
- return " CONTAINS($field, $searchon, 1) > 0 ";
- }
-
- private function escapeTerm( $t ) {
- $t = MediaWikiServices::getInstance()->getContentLanguage()->normalizeForSearch( $t );
- $t = isset( $this->reservedWords[strtoupper( $t )] ) ? '{' . $t . '}' : $t;
- $t = preg_replace( '/^"(.*)"$/', '($1)', $t );
- $t = preg_replace( '/([-&|])/', '\\\\$1', $t );
- return $t;
- }
-
- /**
- * Create or update the search index record for the given page.
- * Title and text should be pre-processed.
- *
- * @param int $id
- * @param string $title
- * @param string $text
- */
- function update( $id, $title, $text ) {
- $dbw = $this->lb->getMaintenanceConnectionRef( DB_MASTER );
- $dbw->replace( 'searchindex',
- [ 'si_page' ],
- [
- 'si_page' => $id,
- 'si_title' => $title,
- 'si_text' => $text
- ], 'SearchOracle::update' );
-
- // Sync the index
- // 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->addQuotes( $dbw->getDBname() . '.' . $dbw->tableName( 'si_text_idx', 'raw' ) ) . ")" );
- $dbw->query( "CALL ctx_ddl.sync_index(" .
- $dbw->addQuotes( $dbw->getDBname() . '.' . $dbw->tableName( 'si_title_idx', 'raw' ) ) . ")" );
- }
-
- /**
- * Update a search index record's title only.
- * Title should be pre-processed.
- *
- * @param int $id
- * @param string $title
- */
- function updateTitle( $id, $title ) {
- $dbw = $this->lb->getConnectionRef( DB_MASTER );
- $dbw->update( 'searchindex',
- [ 'si_title' => $title ],
- [ 'si_page' => $id ],
- 'SearchOracle::updateTitle',
- [] );
- }
-
- public function legalSearchChars( $type = self::CHARS_ALL ) {
- $searchChars = parent::legalSearchChars( $type );
- if ( $type === self::CHARS_ALL ) {
- $searchChars = "\"" . $searchChars;
- }
- return $searchChars;
- }
-}
public function execute( $par ) {
$this->setHeaders();
$this->outputHeader();
+ $this->addHelpLink( 'Help:Blocking_users' );
$out = $this->getOutput();
$out->setPageTitle( $this->msg( 'ipblocklist' ) );
$out->addModuleStyles( [ 'mediawiki.special' ] );
function execute( $par ) {
$this->getOutput()->disallowUserJs();
$this->requireLogin();
+ $this->addHelpLink( 'Manual:Bot_passwords' );
$par = trim( $par );
if ( strlen( $par ) === 0 ) {
public function execute( $par ) {
$this->setHeaders();
$this->outputHeader();
+ $this->addHelpLink( 'Help:Categories' );
$this->getOutput()->allowClickjacking();
$from = $this->getRequest()->getText( 'from', $par );
return $msg->parse();
}
+ public function execute( $par ) {
+ $this->addHelpLink( 'Help:Managing_files' );
+ parent::execute( $par );
+ }
+
protected function getGroupName() {
return 'media';
}
public function execute( $par ) {
$this->setHeaders();
$this->outputHeader();
+ $this->addHelpLink( 'Help:Managing_files' );
if ( $this->including() ) {
$userName = $par;
}
public function execute( $par ) {
+ $this->addHelpLink( 'Help:Managing_files' );
$this->mime = $par ?: $this->getRequest()->getText( 'mime' );
$this->mime = trim( $this->mime );
list( $this->major, $this->minor ) = File::splitMime( $this->mime );
function execute( $par ) {
$this->setHeaders();
$this->outputHeader();
+ $this->addHelpLink( 'Help:Categories' );
$this->getOutput()->allowClickjacking();
$this->getOutput()->addModuleStyles( 'jquery.tablesorter.styles' );
$this->getOutput()->addModules( 'jquery.tablesorter' );
public function execute( $par ) {
parent::execute( $par );
$this->getOutput()->addModules( 'mediawiki.special.unwatchedPages' );
+ $this->addHelpLink( 'Help:Watchlist' );
}
/**
"version-db-mariadb-url": "https://mariadb.org/",
"version-db-percona-url": "http://www.percona.com/software/percona-server",
"version-db-postgres-url": "http://www.postgresql.org/",
- "version-db-oracle-url": "http://www.oracle.com/database/",
"version-db-sqlite-url": "https://www.sqlite.org/",
- "version-db-mssql-url": "https://www.microsoft.com/sql/",
"version-entrypoints": "Entry point URLs",
"version-entrypoints-header-entrypoint": "Entry point",
"version-entrypoints-header-url": "URL",
"version-db-mariadb-url": "{{ignored}}URL to the website of MariaDB",
"version-db-percona-url": "{{ignored}}URL to the website of Percona",
"version-db-postgres-url": "{{ignored}}URL to the website of PostgreSQL",
- "version-db-oracle-url": "{{ignored}}URL to the website of Oracle",
"version-db-sqlite-url": "{{ignored}}URL to the website of SQLite",
- "version-db-mssql-url": "{{ignored}}URL to the website of Microsoft SQL Server",
"version-entrypoints": "Header on [[Special:Version]] above a table that lists the URLs of various entry points in this MediaWiki installation. Entry points are the \"places\" where the wiki's content and information can be accessed in various ways, for instance the standard index.php which shows normal pages, histories etc.",
"version-entrypoints-header-entrypoint": "Header for the first column in the entry points table on [[Special:Version]].\nSee also {{msg-mw|Version-entrypoints}}",
"version-entrypoints-header-url": "Header for the second column in the entry points table on [[Special:Version]].\n{{Identical|URL}}",
private function setUserDefinedTags() {
$dbr = $this->lbFactory->getMainLB()->getConnection( DB_REPLICA );
- $userTags = $dbr->selectFieldValues(
- 'valid_tag',
- 'vt_tag',
- [],
- __METHOD__
- );
+ $userTags = null;
+ if ( $dbr->tableExists( 'valid_tag' ) ) {
+ $userTags = $dbr->selectFieldValues(
+ 'valid_tag',
+ 'vt_tag',
+ [],
+ __METHOD__
+ );
+ }
if ( empty( $userTags ) ) {
$this->output( "No user defined tags to set, moving on...\n" );
$tables[] = 'revision_actor_temp';
}
- if ( in_array( $this->db->getType(), [ 'mysql', 'sqlite', 'oracle' ] ) ) {
+ if ( in_array( $this->db->getType(), [ 'mysql', 'sqlite' ] ) ) {
array_push( $tables, 'searchindex' );
}
$this->db = MediaWikiServices::getInstance()->getDBLoadBalancer()->getConnection( DB_MASTER );
$dbType = $this->db->getType();
- if ( $dbType == 'oracle' ) {
- $suspiciousPrefixes = [ 'pt_', MediaWikiTestCase::ORA_DB_PREFIX ];
- } else {
- $suspiciousPrefixes = [ 'parsertest_', MediaWikiTestCase::DB_PREFIX ];
- }
+ $suspiciousPrefixes = [ 'parsertest_', MediaWikiTestCase::DB_PREFIX ];
if ( in_array( $wgDBprefix, $suspiciousPrefixes ) ) {
throw new MWException( "\$wgDBprefix=$wgDBprefix suggests DB setup is already done" );
}
}
$temporary = $this->useTemporaryTables || $dbType == 'postgres';
- $prefix = $dbType != 'oracle' ? 'parsertest_' : 'pt_';
+ $prefix = 'parsertest_';
$this->dbClone = new CloneDatabase( $this->db, $this->listTables(), $prefix );
$this->dbClone->useTemporaryTables( $temporary );
$this->dbClone->cloneTableStructure();
CloneDatabase::changePrefix( $prefix );
- if ( $dbType == 'oracle' ) {
- $this->db->query( 'BEGIN FILL_WIKI_INFO; END;' );
- # Insert 0 user to prevent FK violations
-
- # Anonymous user
- $this->db->insert( 'user', [
- 'user_id' => 0,
- 'user_name' => 'Anonymous' ] );
- }
-
$teardown[] = function () {
$this->teardownDatabase();
};
$tables = $this->listTables();
foreach ( $tables as $table ) {
- if ( $this->db->getType() == 'oracle' ) {
- $this->db->query( "DROP TABLE pt_$table DROP CONSTRAINTS" );
- } else {
- $this->db->query( "DROP TABLE `parsertest_$table`" );
- }
- }
-
- if ( $this->db->getType() == 'oracle' ) {
- $this->db->query( 'BEGIN FILL_WIKI_INFO; END;' );
+ $this->db->query( "DROP TABLE `parsertest_$table`" );
}
}
private $overriddenServices = [];
/**
- * Table name prefixes. Oracle likes it shorter.
+ * Table name prefix.
*/
const DB_PREFIX = 'unittest_';
- const ORA_DB_PREFIX = 'ut_';
/**
* @var array
'mysql',
'sqlite',
'postgres',
- 'oracle'
];
public function __construct( $name = null, array $data = [], $dataName = '' ) {
}
}
+ // Clear any cached test users so they don't retain references to old services
+ TestUserRegistry::clear();
+
// Re-enable any disabled deprecation warnings
MWDebug::clearLog();
// Restore mw globals
* @since 1.32
*/
public static function getTestPrefixFor( IDatabase $db ) {
- return $db->getType() == 'oracle' ? self::ORA_DB_PREFIX : self::DB_PREFIX;
+ return self::DB_PREFIX;
}
/**
* @since 1.32
*/
protected function addCoreDBData() {
- if ( $this->db->getType() == 'oracle' ) {
- # Insert 0 user to prevent FK violations
- # Anonymous user
- if ( !$this->db->selectField( 'user', '1', [ 'user_id' => 0 ] ) ) {
- $this->db->insert( 'user', [
- 'user_id' => 0,
- 'user_name' => 'Anonymous' ], __METHOD__, [ 'IGNORE' ] );
- }
-
- # Insert 0 page to prevent FK violations
- # Blank page
- if ( !$this->db->selectField( 'page', '1', [ 'page_id' => 0 ] ) ) {
- $this->db->insert( 'page', [
- 'page_id' => 0,
- 'page_namespace' => 0,
- 'page_title' => ' ',
- 'page_restrictions' => null,
- 'page_is_redirect' => 0,
- 'page_is_new' => 0,
- 'page_random' => 0,
- 'page_touched' => $this->db->timestamp(),
- 'page_latest' => 0,
- 'page_len' => 0 ], __METHOD__, [ 'IGNORE' ] );
- }
- }
-
SiteStatsInit::doPlaceholderInit();
User::resetIdByNameCache();
$prefix = self::getTestPrefixFor( $db );
}
- if ( ( $db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) {
+ if ( !self::$useTemporaryTables && self::$reuseDB ) {
$db->tablePrefix( $prefix );
return false;
}
return;
}
- // Assuming this isn't needed for External Store database, and not sure if the procedure
- // would be available there.
- if ( $db->getType() == 'oracle' ) {
- $db->query( 'BEGIN FILL_WIKI_INFO; END;', __METHOD__ );
- }
-
Hooks::run( 'UnitTestsAfterDatabaseSetup', [ $db, $prefix ] );
}
$tablesUsed = array_unique( array_merge( $tablesUsed, $pageTables ) );
}
- // Postgres, Oracle, and MSSQL all use mwuser/pagecontent
+ // Postgres uses mwuser/pagecontent
// instead of user/text. But Postgres does not remap the
// table name in tableExists(), so we mark the real table
// names as being used.
return;
}
- $truncate = in_array( $db->getType(), [ 'oracle', 'mysql' ] );
+ $truncate = in_array( $db->getType(), [ 'mysql' ] );
if ( $truncate ) {
$db->query( 'TRUNCATE TABLE ' . $db->tableName( $tableName ), __METHOD__ );
private function assertNotReal() {
global $wgDBprefix;
- if ( $wgDBprefix !== MediaWikiTestCase::DB_PREFIX &&
- $wgDBprefix !== MediaWikiTestCase::ORA_DB_PREFIX
- ) {
+ if ( $wgDBprefix !== MediaWikiTestCase::DB_PREFIX ) {
throw new MWException( "Can't create user on real database" );
}
}
private function assertWriteAllowed( Database $db ) {
$table = $db->tableName( 'some_table' );
// Trigger a transaction so that rollback() will remove all the tables.
- // Don't do this for MySQL/Oracle as they auto-commit transactions for DDL
+ // Don't do this for MySQL as it auto-commits transactions for DDL
// statements such as CREATE TABLE.
- $useAtomicSection = in_array( $db->getType(), [ 'sqlite', 'postgres', 'mssql' ], true );
+ $useAtomicSection = in_array( $db->getType(), [ 'sqlite', 'postgres' ], true );
try {
$db->dropTable( 'some_table' ); // clear for sanity
$this->assertNotEquals( $db::STATUS_TRX_ERROR, $db->trxStatus() );
'wgServerName' => 'example.org',
'wgScriptPath' => '/w',
'wgDBname' => 'example',
- 'wgDBprefix' => '',
+ 'wgDBprefix' => $this->dbPrefix(),
'wgRCFeeds' => [],
'wgRCEngines' => [],
] );
'server_url' => 'https://example.org',
'server_name' => 'example.org',
'server_script_path' => '/w',
- 'wiki' => 'example',
+ 'wiki' => 'example-' . $this->dbPrefix(),
] ),
$line
);
$lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
$db = $lb->getConnection( DB_MASTER );
$type = $db->getType();
- $prefix = $type === 'oracle' ?
- MediaWikiTestCase::ORA_DB_PREFIX : MediaWikiTestCase::DB_PREFIX;
+ $prefix = MediaWikiTestCase::DB_PREFIX;
$this->oldTablePrefix = $db->tablePrefix();
MediaWikiTestCase::setupTestDB( $db, $prefix );
CloneDatabase::changePrefix( $prefix );