have been removed.
* The $wgUseAjax setting, deprecated in 1.31, is now ignored.
* The $wgSiteSupportPage setting, unused since 1.5, was removed.
+* The $wgBrowserBlacklist setting, deprecated in 1.30, was removed.
* The default quality of JPEG thumbnails generated by GD was reduced from 95 to
80. The quality of JPEG thumbnails is now configurable through the new setting
$wgJpegQuality (default 80). This aligns the quality to what ImageMagick uses.
use 'EditPageGetCheckboxesDefinition' instead.
* Linker::getLinkColour() and DummyLinker::getLinkColour(), deprecated since
1.28, were removed. LinkRenderer::getLinkClasses() should be used instead.
+* Wikimedia\Rdbms\LoadBalancer::getLaggedSlaveMode(), deprecated in 1.28, has
+ been removed. Use Wikimedia\Rdbms\LoadBalancer::getLaggedReplicaMode()
+ instead.
* mw.widgets.CategoryMultiselectWidget now uses TagMultiselectWidget instead of
CapsuleMultiselectWidget. The following methods may no longer be used:
* setItemsFromData: Use setValue instead
*/
$wgLegacyEncoding = false;
-/**
- * @deprecated since 1.30, does nothing
- */
-$wgBrowserBlackList = [];
-
/**
* If set to true, the MediaWiki 1.4 to 1.5 schema conversion will
* create stub reference rows in the text table instead of copying
* Maintain a log of page creations at Special:Log/create?
* @since 1.32
*/
-$wgPageCreationLog = false;
+$wgPageCreationLog = true;
/** @} */ # end logging }
$wgCommentTableSchemaMigrationStage = MIGRATION_OLD;
/**
- * RevisionStore table schema migration stage (content, slots, content_models & slot_roles tables)
+ * RevisionStore table schema migration stage (content, slots, content_models & slot_roles tables).
+ * Use the SCHEMA_COMPAT_XXX flags. Supported values:
+ *
+ * - SCHEMA_COMPAT_OLD
+ * - SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
+ * - SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
+ * - SCHEMA_COMPAT_OLD
+ *
+ * Note that reading the old and new schema at the same time is not supported.
+ * Attempting to set both read bits in $wgMultiContentRevisionSchemaMigrationStage
+ * will result in an InvalidArgumentException.
*
* @see Task: https://phabricator.wikimedia.org/T174028
* @see Commit: https://gerrit.wikimedia.org/r/#/c/378724/
*
* @since 1.32
- * @var int One of the MIGRATION_* constants
+ * @var int An appropriate combination of SCHEMA_COMPAT_XXX flags.
*/
$wgMultiContentRevisionSchemaMigrationStage = MIGRATION_OLD;
define( 'SHELL_MAX_ARG_STRLEN', '100000' );
/**@}*/
+/**@{
+ * Schema compatibility flags.
+ *
+ * Used as flags in a bit field that indicates whether the old or new schema (or both)
+ * are read or written.
+ *
+ * - SCHEMA_COMPAT_WRITE_OLD: Whether information is written to the old schema.
+ * - SCHEMA_COMPAT_READ_OLD: Whether information stored in the old schema is read.
+ * - SCHEMA_COMPAT_WRITE_NEW: Whether information is written to the new schema.
+ * - SCHEMA_COMPAT_READ_NEW: Whether information stored in the new schema is read.
+ */
+define( 'SCHEMA_COMPAT_WRITE_OLD', 0x01 );
+define( 'SCHEMA_COMPAT_READ_OLD', 0x02 );
+define( 'SCHEMA_COMPAT_WRITE_NEW', 0x10 );
+define( 'SCHEMA_COMPAT_READ_NEW', 0x20 );
+define( 'SCHEMA_COMPAT_WRITE_BOTH', SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_WRITE_NEW );
+define( 'SCHEMA_COMPAT_READ_BOTH', SCHEMA_COMPAT_READ_OLD | SCHEMA_COMPAT_READ_NEW );
+define( 'SCHEMA_COMPAT_OLD', SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_READ_OLD );
+define( 'SCHEMA_COMPAT_NEW', SCHEMA_COMPAT_WRITE_NEW | SCHEMA_COMPAT_READ_NEW );
+/**@}*/
+
/**@{
* Schema change migration flags.
*
* Used as values of a feature flag for an orderly transition from an old
- * schema to a new schema.
+ * schema to a new schema. The numeric values of these constants are compatible with the
+ * SCHEMA_COMPAT_XXX bitfield semantics. High bits are used to ensure that the numeric
+ * ordering follows the order in which the migration stages should be used.
*
* - MIGRATION_OLD: Only read and write the old schema. The new schema need not
* even exist. This is used from when the patch is merged until the schema
* - MIGRATION_NEW: Only read and write the new schema. The old schema (and the
* feature flag) may now be removed.
*/
-define( 'MIGRATION_OLD', 0 );
-define( 'MIGRATION_WRITE_BOTH', 1 );
-define( 'MIGRATION_WRITE_NEW', 2 );
-define( 'MIGRATION_NEW', 3 );
+define( 'MIGRATION_OLD', 0x00000000 | SCHEMA_COMPAT_OLD );
+define( 'MIGRATION_WRITE_BOTH', 0x10000000 | SCHEMA_COMPAT_READ_BOTH | SCHEMA_COMPAT_WRITE_BOTH );
+define( 'MIGRATION_WRITE_NEW', 0x20000000 | SCHEMA_COMPAT_READ_BOTH | SCHEMA_COMPAT_WRITE_NEW );
+define( 'MIGRATION_NEW', 0x30000000 | SCHEMA_COMPAT_NEW );
/**@}*/
use MediaWiki\Storage\RevisionFactory;
use MediaWiki\Storage\RevisionLookup;
use MediaWiki\Storage\RevisionStore;
-use MediaWiki\Storage\RevisionStoreFactory;
use OldRevisionImporter;
use UploadRevisionImporter;
use Wikimedia\Rdbms\LBFactory;
return $this->getService( 'RevisionStore' );
}
- /**
- * @since 1.32
- * @return RevisionStoreFactory
- */
- public function getRevisionStoreFactory() {
- return $this->getService( 'RevisionStoreFactory' );
- }
-
/**
* @since 1.31
* @return RevisionLookup
use MediaWiki\Shell\CommandFactory;
use MediaWiki\Storage\BlobStoreFactory;
use MediaWiki\Storage\NameTableStore;
-use MediaWiki\Storage\RevisionStoreFactory;
+use MediaWiki\Storage\RevisionStore;
use MediaWiki\Storage\SqlBlobStore;
use Wikimedia\ObjectFactory;
},
'RevisionStore' => function ( MediaWikiServices $services ) {
- return $services->getRevisionStoreFactory()->getRevisionStore();
- },
-
- 'RevisionStoreFactory' => function ( MediaWikiServices $services ) {
/** @var SqlBlobStore $blobStore */
$blobStore = $services->getService( '_SqlBlobStore' );
- $config = $services->getMainConfig();
- $store = new RevisionStoreFactory(
+ $store = new RevisionStore(
$services->getDBLoadBalancer(),
$blobStore,
$services->getMainWANObjectCache(),
$services->getContentModelStore(),
$services->getSlotRoleStore(),
$services->getMainConfig()->get( 'MultiContentRevisionSchemaMigrationStage' ),
- $services->getActorMigration(),
- LoggerFactory::getInstance( 'RevisionStore' ),
- $config->get( 'ContentHandlerUseDB' )
+ $services->getActorMigration()
);
+ $store->setLogger( LoggerFactory::getInstance( 'RevisionStore' ) );
+
+ $config = $services->getMainConfig();
+ $store->setContentHandlerUseDB( $config->get( 'ContentHandlerUseDB' ) );
+
return $store;
},
// TODO: MCR: check the role and the content's model against the list of supported
// roles, see T194046.
+ if ( $role !== 'main' ) {
+ throw new InvalidArgumentException( 'Only the main slot is presently supported' );
+ }
+
$this->slotsUpdate->modifyContent( $role, $content );
}
*/
private $slotRoleStore;
- /** @var int One of the MIGRATION_* constants */
+ /** @var int An appropriate combination of SCHEMA_COMPAT_XXX flags. */
private $mcrMigrationStage;
/**
* @param CommentStore $commentStore
* @param NameTableStore $contentModelStore
* @param NameTableStore $slotRoleStore
- * @param int $migrationStage
+ * @param int $mcrMigrationStage An appropriate combination of SCHEMA_COMPAT_XXX flags
* @param ActorMigration $actorMigration
* @param bool|string $wikiId
+ *
+ * @throws MWException if $mcrMigrationStage or $wikiId is invalid.
*/
public function __construct(
LoadBalancer $loadBalancer,
CommentStore $commentStore,
NameTableStore $contentModelStore,
NameTableStore $slotRoleStore,
- $migrationStage,
+ $mcrMigrationStage,
ActorMigration $actorMigration,
$wikiId = false
) {
Assert::parameterType( 'string|boolean', $wikiId, '$wikiId' );
- Assert::parameterType( 'integer', $migrationStage, '$migrationStage' );
+ Assert::parameterType( 'integer', $mcrMigrationStage, '$mcrMigrationStage' );
+ Assert::parameter(
+ ( $mcrMigrationStage & SCHEMA_COMPAT_READ_BOTH ) !== SCHEMA_COMPAT_READ_BOTH,
+ '$mcrMigrationStage',
+ 'Reading from the old and the new schema at the same time is not supported.'
+ );
+ Assert::parameter(
+ ( $mcrMigrationStage & SCHEMA_COMPAT_READ_BOTH ) !== 0,
+ '$mcrMigrationStage',
+ 'Reading needs to be enabled for the old or the new schema.'
+ );
+ Assert::parameter(
+ ( $mcrMigrationStage & SCHEMA_COMPAT_WRITE_BOTH ) !== 0,
+ '$mcrMigrationStage',
+ 'Writing needs to be enabled for the old or the new schema.'
+ );
+ Assert::parameter(
+ ( $mcrMigrationStage & SCHEMA_COMPAT_READ_OLD ) === 0
+ || ( $mcrMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) !== 0,
+ '$mcrMigrationStage',
+ 'Cannot read the old schema when not also writing it.'
+ );
+ Assert::parameter(
+ ( $mcrMigrationStage & SCHEMA_COMPAT_READ_NEW ) === 0
+ || ( $mcrMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) !== 0,
+ '$mcrMigrationStage',
+ 'Cannot read the new schema when not also writing it.'
+ );
$this->loadBalancer = $loadBalancer;
$this->blobStore = $blobStore;
$this->commentStore = $commentStore;
$this->contentModelStore = $contentModelStore;
$this->slotRoleStore = $slotRoleStore;
- $this->mcrMigrationStage = $migrationStage;
+ $this->mcrMigrationStage = $mcrMigrationStage;
$this->actorMigration = $actorMigration;
$this->wikiId = $wikiId;
$this->logger = new NullLogger();
}
+ /**
+ * @param int $flags A combination of SCHEMA_COMPAT_XXX flags.
+ * @return bool True if all the given flags were set in the $mcrMigrationStage
+ * parameter passed to the constructor.
+ */
+ private function hasMcrSchemaFlags( $flags ) {
+ return ( $this->mcrMigrationStage & $flags ) === $flags;
+ }
+
public function setLogger( LoggerInterface $logger ) {
$this->logger = $logger;
}
* @throws MWException
*/
public function setContentHandlerUseDB( $contentHandlerUseDB ) {
- if ( !$contentHandlerUseDB && $this->mcrMigrationStage > MIGRATION_OLD ) {
- throw new MWException(
- 'Content model must be stored in the database for multi content revision migration.'
- );
+ if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_NEW )
+ || $this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_NEW )
+ ) {
+ if ( !$contentHandlerUseDB ) {
+ throw new MWException(
+ 'Content model must be stored in the database for multi content revision migration.'
+ );
+ }
}
$this->contentHandlerUseDB = $contentHandlerUseDB;
}
);
}
- // While inserting into the old schema make sure only the main slot is allowed.
- // TODO: support extra slots in MIGRATION_WRITE_BOTH mode!
- if ( $this->mcrMigrationStage <= MIGRATION_WRITE_BOTH && $slotRoles !== [ 'main' ] ) {
+ // If we are not writing into the new schema, we can't support extra slots.
+ if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_NEW ) && $slotRoles !== [ 'main' ] ) {
throw new InvalidArgumentException(
- 'Only the main slot is supported with MCR migration mode <= MIGRATION_WRITE_BOTH!'
+ 'Only the main slot is supported when not writing to the MCR enabled schema!'
+ );
+ }
+
+ // As long as we are not reading from the new schema, we don't want to write extra slots.
+ if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_NEW ) && $slotRoles !== [ 'main' ] ) {
+ throw new InvalidArgumentException(
+ 'Only the main slot is supported when not reading from the MCR enabled schema!'
);
}
);
// Trigger exception if the main slot is missing.
- // Technically, this could go away with MIGRATION_NEW: while
+ // Technically, this could go away after MCR migration: while
// calling code may require a main slot to exist, RevisionStore
// really should not know or care about that requirement.
$rev->getSlot( 'main', RevisionRecord::RAW );
$newSlots[$role] = $slot;
// Write the main slot's text ID to the revision table for backwards compatibility
- if ( $slot->getRole() === 'main' && $this->mcrMigrationStage <= MIGRATION_WRITE_BOTH ) {
+ if ( $slot->getRole() === 'main'
+ && $this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_OLD )
+ ) {
$blobAddress = $slot->getAddress();
$this->updateRevisionTextId( $dbw, $revisionId, $blobAddress );
}
}
// Write the main slot's text ID to the revision table for backwards compatibility
- if ( $protoSlot->getRole() === 'main' && $this->mcrMigrationStage <= MIGRATION_WRITE_BOTH ) {
+ if ( $protoSlot->getRole() === 'main'
+ && $this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_OLD )
+ ) {
$this->updateRevisionTextId( $dbw, $revisionId, $blobAddress );
}
- if ( $this->mcrMigrationStage >= MIGRATION_WRITE_BOTH ) {
+ if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_NEW ) ) {
if ( $protoSlot->hasContentId() ) {
$contentId = $protoSlot->getContentId();
} else {
$revisionRow['rev_id'] = $rev->getId();
}
- if ( $this->mcrMigrationStage <= MIGRATION_WRITE_BOTH ) {
- // In non MCR more this IF section will relate to the main slot
+ if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_OLD ) ) {
+ // In non MCR mode this IF section will relate to the main slot
$mainSlot = $rev->getSlot( 'main' );
$model = $mainSlot->getModel();
$format = $mainSlot->getFormat();
$blobFlags = null;
if ( is_object( $row ) ) {
- if ( $this->mcrMigrationStage >= MIGRATION_NEW ) {
+ if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_NEW ) ) {
// Don't emulate from a row when using the new schema.
// Emulating from an array is still OK.
throw new LogicException( 'Can\'t emulate the main slot when using MCR schema.' );
$queryFlags,
Title $title
) {
- if ( $this->mcrMigrationStage < MIGRATION_NEW ) {
- // TODO: in MIGRATION_WRITE_BOTH, we could use the old and the new method:
- // e.g. call emulateMainSlot_1_29() if loadSlotRecords() fails.
-
+ if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_NEW ) ) {
$mainSlot = $this->emulateMainSlot_1_29( $revisionRow, $queryFlags, $title );
$slots = new RevisionSlots( [ 'main' => $mainSlot ] );
} else {
}
if ( !empty( $fields['text_id'] ) ) {
- if ( $this->mcrMigrationStage >= MIGRATION_NEW ) {
- throw new MWException( "Cannot use text_id field with MCR schema" );
+ if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_OLD ) ) {
+ throw new MWException( "The text_id field is only available in the pre-MCR schema" );
}
if ( !empty( $fields['content'] ) ) {
/**
* Finds the ID of a content row for a given revision and slot role.
* This can be used to re-use content rows even while the content ID
- * is still missing from SlotRecords, in MIGRATION_WRITE_BOTH mode.
+ * is still missing from SlotRecords, when writing to both the old and
+ * the new schema during MCR schema migration.
*
* @todo remove after MCR schema migration is complete.
*
* @return int|null
*/
private function findSlotContentId( IDatabase $db, $revId, $role ) {
- if ( $this->mcrMigrationStage < MIGRATION_WRITE_BOTH ) {
+ if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_NEW ) ) {
return null;
}
* - 'page': Join with the page table, and select fields to identify the page
* - 'user': Join with the user table, and select the user name
* - 'text': Join with the text table, and select fields to load page text. This
- * option is deprecated in MW 1.32 with MCR migration stage MIGRATION_WRITE_BOTH,
- * and disallowed with MIGRATION_MEW.
+ * option is deprecated in MW 1.32 when the MCR migration flag SCHEMA_COMPAT_WRITE_NEW
+ * is set, and disallowed when SCHEMA_COMPAT_READ_OLD is not set.
*
* @return array With three keys:
* - tables: (string[]) to include in the `$table` to `IDatabase->select()`
$ret['fields'] = array_merge( $ret['fields'], $actorQuery['fields'] );
$ret['joins'] = array_merge( $ret['joins'], $actorQuery['joins'] );
- if ( $this->mcrMigrationStage < MIGRATION_NEW ) {
+ if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_OLD ) ) {
$ret['fields'][] = 'rev_text_id';
if ( $this->contentHandlerUseDB ) {
}
if ( in_array( 'text', $options, true ) ) {
- if ( $this->mcrMigrationStage === MIGRATION_NEW ) {
+ if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_OLD ) ) {
throw new InvalidArgumentException( 'text table can no longer be joined directly' );
- } elseif ( $this->mcrMigrationStage >= MIGRATION_WRITE_BOTH ) {
+ } elseif ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_OLD ) ) {
+ // NOTE: even when this class is set to not read from the old schema, callers
+ // should still be able to join against the text table, as long as we are still
+ // writing the old schema for compatibility.
wfDeprecated( __METHOD__ . ' with `text` option', '1.32' );
}
'joins' => [],
];
- if ( $this->mcrMigrationStage < MIGRATION_NEW ) {
+ if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_OLD ) ) {
$db = $this->getDBConnectionRef( DB_REPLICA );
$ret['tables']['slots'] = 'revision';
$ret['fields']['model_name'] = 'NULL';
}
}
-
- // XXX: in MIGRATION_WRITE_BOTH mode, emulate *and* select - using a UNION?
- // See Anomie's idea at <https://gerrit.wikimedia.org/r/c/416465/
- // 8..10/includes/Storage/RevisionStore.php#2113>
} else {
$ret['tables'][] = 'slots';
$ret['tables'][] = 'slot_roles';
'joins' => $commentQuery['joins'] + $actorQuery['joins'],
];
- if ( $this->mcrMigrationStage < MIGRATION_NEW ) {
+ if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_OLD ) ) {
$ret['fields'][] = 'ar_text_id';
if ( $this->contentHandlerUseDB ) {
+++ /dev/null
-<?php
-
-/**
- * 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
- *
- * Attribution notice: when this file was created, much of its content was taken
- * from the Revision.php file as present in release 1.30. Refer to the history
- * of that file for original authorship.
- *
- * @file
- */
-
-namespace MediaWiki\Storage;
-
-use ActorMigration;
-use CommentStore;
-use Psr\Log\LoggerInterface;
-use WANObjectCache;
-use Wikimedia\Assert\Assert;
-use Wikimedia\Rdbms\LoadBalancer;
-
-/**
- * @since 1.32
- */
-class RevisionStoreFactory {
-
- /** @var SqlBlobStore */
- private $blobStore;
-
- /** @var LoadBalancer */
- private $loadBalancer;
-
- /** @var WANObjectCache */
- private $cache;
-
- /** @var CommentStore */
- private $commentStore;
-
- /** @var ActorMigration */
- private $actorMigration;
-
- /** @var NameTableStore */
- private $contentModelStore;
-
- /** @var NameTableStore */
- private $slotRoleStore;
-
- /** @var int One of the MIGRATION_* constants */
- private $mcrMigrationStage;
-
- /**
- * @var bool
- * @see $wgContentHandlerUseDB
- */
- private $contentHandlerUseDB;
-
- /** @var LoggerInterface */
- private $logger;
-
- /**
- * @todo $blobStore should be allowed to be any BlobStore!
- *
- * @param LoadBalancer $loadBalancer
- * @param SqlBlobStore $blobStore
- * @param WANObjectCache $cache
- * @param CommentStore $commentStore
- * @param NameTableStore $contentModelStore
- * @param NameTableStore $slotRoleStore
- * @param int $migrationStage
- * @param ActorMigration $actorMigration
- * @param LoggerInterface $logger
- * @param bool $contentHandlerUseDB see {@link $wgContentHandlerUseDB}
- */
- public function __construct(
- LoadBalancer $loadBalancer,
- SqlBlobStore $blobStore,
- WANObjectCache $cache,
- CommentStore $commentStore,
- NameTableStore $contentModelStore,
- NameTableStore $slotRoleStore,
- $migrationStage,
- ActorMigration $actorMigration,
- LoggerInterface $logger,
- $contentHandlerUseDB
- ) {
- Assert::parameterType( 'integer', $migrationStage, '$migrationStage' );
-
- $this->loadBalancer = $loadBalancer;
- $this->blobStore = $blobStore;
- $this->cache = $cache;
- $this->commentStore = $commentStore;
- $this->contentModelStore = $contentModelStore;
- $this->slotRoleStore = $slotRoleStore;
- $this->mcrMigrationStage = $migrationStage;
- $this->actorMigration = $actorMigration;
- $this->logger = $logger;
- $this->contentHandlerUseDB = $contentHandlerUseDB;
- }
-
- /**
- * @since 1.32
- *
- * @param bool|string $wikiId false for the current domain / wikid
- *
- * @return RevisionStore for the given wikiId with all necessary services and a logger
- */
- public function getRevisionStore( $wikiId = false ) {
- Assert::parameterType( 'string|boolean', $wikiId, '$wikiId' );
-
- $store = new RevisionStore(
- $this->loadBalancer,
- $this->blobStore,
- $this->cache,
- $this->commentStore,
- $this->contentModelStore,
- $this->slotRoleStore,
- $this->mcrMigrationStage,
- $this->actorMigration,
- $wikiId
- );
-
- $store->setLogger( $this->logger );
- $store->setContentHandlerUseDB( $this->contentHandlerUseDB );
-
- return $store;
- }
-
-}
"apihelp-protect-example-protect": "Een pagina beveiligen.",
"apihelp-purge-param-forcelinkupdate": "Werk de koppelingstabellen bij.",
"apihelp-purge-param-forcerecursivelinkupdate": "Werk de koppelingentabel bij, en werk de koppelingstabellen bij voor alle pagina's die deze pagina als sjabloon gebruiken.",
+ "apihelp-query+allcategories-summary": "Alle categorieën doorlopen.",
"apihelp-query+allcategories-param-dir": "Richting om in te sorteren.",
"apihelp-query+allcategories-param-limit": "Hoeveel categorieën te tonen.",
"apihelp-query+allcategories-paramvalue-prop-size": "Voegt het aantal pagina's in de categorie toe.",
"apihelp-query+allpages-param-limit": "Het totaal aantal pagina's dat getoont moeten worden.",
"apihelp-query+allredirects-summary": "Toon alle doorverwijzingen naar een naamruimte.",
"apihelp-query+allredirects-paramvalue-prop-title": "Voegt de titel van de doorverwijzing toe.",
+ "apihelp-query+allredirects-param-limit": "Hoeveel items er in totaal moeten worden getoond.",
"apihelp-query+allrevisions-summary": "Toon alle versies.",
+ "apihelp-query+allrevisions-param-namespace": "Alleen pagina's in deze naamruimte weergeven.",
"apihelp-query+allrevisions-example-user": "Toon de laatste 50 bijdragen van gebruiker <kbd>Example</kbd>.",
"apihelp-query+mystashedfiles-paramvalue-prop-type": "Vraag het MIME- en mediatype van het bestand op.",
"apihelp-query+mystashedfiles-param-limit": "Hoeveel bestanden te tonen.",
"apihelp-query+alltransclusions-param-namespace": "De door te lopen naamruimte.",
+ "apihelp-query+alltransclusions-param-limit": "Hoeveel items er in totaal moeten worden getoond.",
"apihelp-query+allusers-param-dir": "Richting om in te sorteren.",
"apihelp-query+allusers-param-excludegroup": "Sluit gebruikers in de gegeven groepen uit.",
"apihelp-query+allusers-paramvalue-prop-blockinfo": "Voegt informatie over een actuele blokkade van de gebruiker toe.",
"apihelp-query+categorymembers-param-dir": "Richting om in te sorteren.",
"apihelp-query+categorymembers-example-simple": "Toon de eerste 10 pagina's in <kbd>Category:Physics</kbd>.",
"apihelp-query+deletedrevisions-param-tag": "Alleen revisies met dit label weergeven.",
+ "apihelp-query+deletedrevs-paraminfo-modes": "{{PLURAL:$1|Modus|Modi}}: $2",
"apihelp-query+deletedrevs-param-tag": "Alleen revisies met dit label weergeven.",
"apihelp-query+embeddedin-param-namespace": "De door te lopen naamruimte.",
+ "apihelp-query+filearchive-example-simple": "Toon een lijst met alle verwijderde bestanden.",
"apihelp-query+fileusage-paramvalue-prop-pageid": "Pagina-ID van elke pagina.",
"apihelp-query+fileusage-paramvalue-prop-title": "Titel van elke pagina.",
+ "apihelp-query+imageinfo-paramvalue-prop-mediatype": "Voegt het mediatype van het bestand toe.",
"apihelp-query+imageusage-param-namespace": "De door te lopen naamruimte.",
"apihelp-query+imageusage-example-simple": "Toon pagina's die [[:File:Albert Einstein Head.jpg]] gebruiken.",
"apihelp-query+imageusage-example-generator": "Toon informatie over pagina's die [[:File:Albert Einstein Head.jpg]] gebruiken.",
"apihelp-query+iwbacklinks-param-prefix": "Voorvoegsel voor de interwiki.",
+ "apihelp-query+iwlinks-paramvalue-prop-url": "Voegt de volledige URL toe.",
"apihelp-query+langbacklinks-example-simple": "Toon de pagina's die verwijzen naar [[:fr:Test]].",
+ "apihelp-query+langlinks-paramvalue-prop-url": "Voegt de volledige URL toe.",
"apihelp-query+linkshere-paramvalue-prop-pageid": "Pagina-ID van elke pagina.",
"apihelp-query+linkshere-paramvalue-prop-title": "Titel van elke pagina.",
"apihelp-query+linkshere-param-namespace": "Toon alleen pagina's in deze naamruimten.",
// Fetch all rows in case the DB needs that to properly lock them.
}
- // Get all of the page revisions
+ // If SCHEMA_COMPAT_WRITE_OLD is set, also select all extra fields we still write,
+ // so we can copy it to the archive table.
+ // We know the fields exist, otherwise SCHEMA_COMPAT_WRITE_OLD could not function.
+ if ( $wgMultiContentRevisionSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
+ $revQuery['fields'][] = 'rev_text_id';
+
+ if ( $wgContentHandlerUseDB ) {
+ $revQuery['fields'][] = 'rev_content_model';
+ $revQuery['fields'][] = 'rev_content_format';
+ }
+ }
+
+ // Get all of the page revisions
$res = $dbw->select(
$revQuery['tables'],
$revQuery['fields'],
] + $commentStore->insert( $dbw, 'ar_comment', $comment )
+ $actorMigration->getInsertValues( $dbw, 'ar_user', $user );
- if ( $wgMultiContentRevisionSchemaMigrationStage < MIGRATION_NEW ) {
+ if ( $wgMultiContentRevisionSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
$rowInsert['ar_text_id'] = $row->rev_text_id;
- }
- if (
- $wgContentHandlerUseDB &&
- $wgMultiContentRevisionSchemaMigrationStage <= MIGRATION_WRITE_BOTH
- ) {
- $rowInsert['ar_content_model'] = $row->rev_content_model;
- $rowInsert['ar_content_format'] = $row->rev_content_format;
+ if ( $wgContentHandlerUseDB ) {
+ $rowInsert['ar_content_model'] = $row->rev_content_model;
+ $rowInsert['ar_content_format'] = $row->rev_content_format;
+ }
}
+
$rowsInsert[] = $rowInsert;
$revids[] = $row->rev_id;
"Alp Er Tunqa",
"Baloch Khan",
"Fitoschido",
- "Alireza Ivaz"
+ "Alireza Ivaz",
+ "Iriman"
]
},
"tog-underline": "خط کشیدن زیر پیوندها:",
"filehist-dimensions": "ابعاد",
"filehist-filesize": "اندازهٔ پرونده",
"filehist-comment": "توضیح",
- "imagelinks": "بهکاررفتن پرونده",
+ "imagelinks": "کاربرد پرونده",
"linkstoimage": "{{PLURAL:$1|صفحهٔ|صفحههای}} زیر به این تصویر پیوند {{PLURAL:$1|دارد|دارند}}:",
"linkstoimage-more": "بیش از $1 صفحه به این پرونده پیوند {{PLURAL:$1|دارد|دارند}}.\nفهرست زیر تنها {{PLURAL:$1|اولین پیوند|اولین $1 پیوند}} به این صفحه را نشان میدهد.\n[[Special:WhatLinksHere/$2|فهرست کامل]] نیز موجود است.",
"nolinkstoimage": "این پرونده در هیچ صفحهای به کار نرفتهاست.",
"nav-login-createaccount": "Oanmelde",
"logout": "Ofmelde",
"userlogout": "Ofmelde",
- "notloggedin": "Net oanmelde",
+ "notloggedin": "Net oanmeld",
"userlogin-noaccount": "Hasto gjin akkount?",
"userlogin-joinproject": "Meidwaan {{SITENAME}}",
"createaccount": "Registrearje",
"upload": "Bied triem oan",
"uploadbtn": "Bied triem oan",
"reuploaddesc": "Werom nei oanbied-side.",
- "uploadnologin": "Net oanmelde",
+ "uploadnologin": "Net oanmeld",
"uploadnologintext": "Jo moatte [[Special:UserLogin|oanmeld]] wêze om in triem oanbiede te kinnen.",
"upload_directory_missing": "De heechlaadmap ($1) is der net en koe net oanmakke wurde troch de webserver.",
"upload_directory_read_only": "De webserver kin net skriuwe yn de oanbiedpad ($1).",
"tooltip-undo": "\"Undo\" reverts this edit and opens the edit form in preview mode. It allows adding a reason in the summary.",
"tooltip-summary": "ꯑꯇꯦꯟꯕꯥ ꯀꯨꯞꯅꯥ ꯁꯟꯗꯣꯛꯅꯩ ꯇꯥꯛꯄꯥ ꯏꯌꯨ",
"simpleantispam-label": "Anti-spam check.\nDo <strong>not</strong> fill this in!",
+ "pageinfo-header-edits": "ꯄꯨꯋꯥꯔꯤ ꯁꯦꯝꯒꯠꯄ",
"pageinfo-header-restrictions": "ꯉꯥꯛꯊꯣꯛꯂꯕꯥ ꯂꯥꯃꯥꯏ",
"pageinfo-robot-noindex": "ꯌꯥꯍꯟꯗꯕꯥ",
"pageinfo-subpages-name": "ꯂꯥꯃꯥꯏꯁꯤ ꯒꯤ ꯃꯅꯨꯡ ꯆꯟꯕꯥ ꯀꯨꯞꯊꯕꯥ ꯂꯥꯃꯥꯏꯁꯤꯡ",
"pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|redirect|redirects}}; $3 {{PLURAL:$3|non-redirect|non-redirects}})",
+ "pageinfo-firstuser": "ꯂꯥꯃꯥꯏ ꯁꯥꯔꯤꯕ ꯃꯤꯑꯣꯏꯁꯤꯡ",
+ "pageinfo-firsttime": "ꯂꯥꯃꯥꯏ ꯁꯥꯈꯤꯕꯒꯤ ꯆꯩꯆꯠ",
+ "pageinfo-lastuser": "ꯈꯋꯥꯏꯗꯒꯤ ꯅꯧꯕ ꯁꯦꯝꯒꯠꯂꯛꯂꯤꯕꯁꯤꯡ",
+ "pageinfo-lasttime": "ꯅꯧꯔꯤꯕ ꯁꯦꯝꯒꯠꯄꯒꯤ ꯆꯩꯆꯠ",
+ "pageinfo-edits": "ꯑꯄꯨꯟꯕ ꯁꯦꯝꯒꯠꯄꯒꯤ ꯃꯁꯤꯡ",
+ "pageinfo-authors": "ꯑꯄꯨꯟꯕ ꯑꯈꯟꯅꯕ ꯑꯌꯤꯕꯁꯤꯡꯒꯤ ꯃꯁꯤꯡ",
"pageinfo-magic-words": "Magic {{PLURAL:$1|word|words}} ($1)",
"pageinfo-toolboxlink": "ꯂꯥꯃꯥꯏꯒꯤ ꯃꯇꯥꯡꯗꯥ",
"pageinfo-contentpage-yes": "ꯍꯣꯏ",
"rcfilters-savedqueries-apply-and-setdefault-label": "د فرض په ډول د فيلټر جوړول",
"rcfilters-savedqueries-cancel-label": "ناگارل",
"rcfilters-savedqueries-add-new-title": "د امستنې اوسنۍ فيلټر خوندي کړي",
+ "rcfilters-restore-default-filters": "د ډيفاولټ فلټرونه بیا تازه کول",
"rcfilters-search-placeholder": "د فلټر بدلونونه (د مینو کارول یا د فلټر نوم لټونه)",
"rcfilters-invalid-filter": "غلط فلټر",
"rcfilters-empty-filter": "هيڅ فعال فلټر نشته. ټولي سمونې ښکاره شوي.",
"prefs-editor": "Used in [[Special:Preferences]], tab \"Editing\" ({{int:prefs-editing}}).\n\n{{Identical|Editor}}",
"prefs-preview": "Used in [[Special:Preferences]], tab \"Editing\".\n{{Identical|Preview}}",
"prefs-advancedrc": "Used in [[Special:Preferences]], tab \"Recent changes\".\n{{Identical|Advanced options}}",
- "prefs-opt-out": "Used in [[Special:Preferences]], tab \"Recent changes\".",
+ "prefs-opt-out": "Used in [[Special:Preferences]], tabs \"Recent changes\" and \"Watchlist\".",
"prefs-advancedrendering": "Used in [[Special:Preferences]], tab \"Appearence\".\n{{Identical|Advanced options}}",
"prefs-advancedsearchoptions": "Used in [[Special:Preferences]], tab \"Search options\".\n{{Identical|Advanced options}}",
"prefs-advancedwatchlist": "Used in [[Special:Preferences]], tab \"Watchlist\".\n{{Identical|Advanced options}}",
"december-date": "$1. децембар",
"period-am": "преподне",
"period-pm": "поподне",
- "pagecategories": "{{PLURAL:$1|Категорија|Категорије|Категорија}}",
+ "pagecategories": "{{PLURAL:$1|Категорија|Категорије}}",
"category_header": "Странице у категорији „$1“",
"subcategories": "Поткатегорије",
"category-media-header": "Датотеке у категорији „$1“",
"permalink": "Трајна веза",
"print": "Штампај",
"view": "Погледај",
- "view-foreign": "Ð\92иди на пројекту $1",
+ "view-foreign": "Ð\9fогледаÑ\98 на пројекту $1",
"edit": "Уреди",
"edit-local": "Уреди локални опис",
"create": "Направи",
"pagetitle-view-mainpage": "{{SITENAME}}",
"backlinksubtitle": "← $1",
"retrievedfrom": "Преузето из „$1“",
- "youhavenewmessages": "Имате $1 ($2).",
+ "youhavenewmessages": "{{PLURAL:$3|Имате}} $1 ($2).",
"youhavenewmessagesfromusers": "{{PLURAL:$4|Имате}} $1 од {{PLURAL:$3|другог корисника|$3 корисника}} ($2).",
"youhavenewmessagesmanyusers": "Имате $1 од много корисника ($2).",
"newmessageslinkplural": "{{PLURAL:$1|нову поруку|нове поруке|нових порука}}",
"sort-descending": "Поређај опадајуће",
"sort-ascending": "Поређај растуће",
"nstab-main": "Страница",
- "nstab-user": "{{GENDER:{{BASEPAGENAME}}|Корисник|Корисница|Корисник}}",
+ "nstab-user": "Корисничка страница",
"nstab-media": "Медији",
- "nstab-special": "Ð\9fоÑ\81ебно",
- "nstab-project": "Ð\9fÑ\80оÑ\98екаÑ\82",
+ "nstab-special": "Ð\9fоÑ\81ебна Ñ\81Ñ\82Ñ\80аниÑ\86а",
+ "nstab-project": "СÑ\82Ñ\80аниÑ\86а пÑ\80оÑ\98екÑ\82а",
"nstab-image": "Датотека",
"nstab-mediawiki": "Порука",
"nstab-template": "Шаблон",
"userlogin-yourpassword-ph": "Унесите своју лозинку",
"createacct-yourpassword-ph": "Унесите лозинку",
"yourpasswordagain": "Поново унеси лозинку:",
- "createacct-yourpasswordagain": "Потврди лозинку",
+ "createacct-yourpasswordagain": "Потврдите лозинку",
"createacct-yourpasswordagain-ph": "Унесите лозинку поново",
"userlogin-remembermypassword": "Остави ме пријављеног/у",
"userlogin-signwithsecure": "Користите сигурну конекцију",
"showpreview": "Прикажи претпреглед",
"showdiff": "Прикажи измене",
"blankarticle": "<strong>Упозорење:</strong> Страница коју правите је празна.\nАко још једном притиснете „$1”, страница ће бити направљена без икаквог садржаја.",
- "anoneditwarning": "<strong>УпозоÑ\80еÑ\9aе:</strong> Ð\9dиÑ\81Ñ\82е пÑ\80иÑ\98авÑ\99ени. Ð\90ко обÑ\98авиÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83, Ð\92аÑ\88а IP адÑ\80еÑ\81а Ñ\9bе биÑ\82и Ñ\98авно видÑ\99ива Ñ\83 Ñ\9aеноÑ\98 иÑ\81Ñ\82оÑ\80иÑ\98и измена и дÑ\80Ñ\83где. Ð\90ко Ñ\81е <strong>[$1 пÑ\80иÑ\98авиÑ\82е]</strong> или <strong>[$2 оÑ\82воÑ\80иÑ\82е налог]</strong>, поÑ\80ед оÑ\81Ñ\82алиÑ\85 погодноÑ\81Ñ\82и коÑ\98е добиÑ\98аÑ\82е Ð\92аÑ\88е измене Ñ\9bе биÑ\82и пÑ\80ипиÑ\81иване Ð\92аÑ\88ем коÑ\80иÑ\81ниÑ\87ком именÑ\83.",
+ "anoneditwarning": "<strong>УпозоÑ\80еÑ\9aе:</strong> Ð\9dиÑ\81Ñ\82е пÑ\80иÑ\98авÑ\99ени. Ð\92аÑ\88а IP адÑ\80еÑ\81а Ñ\9bе биÑ\82и Ñ\98авно видÑ\99ива ако напÑ\80авиÑ\82е некÑ\83 изменÑ\83. Ð\90ко Ñ\81е <strong>[$1 пÑ\80иÑ\98авиÑ\82е]</strong> или <strong>[$2 оÑ\82воÑ\80иÑ\82е налог]</strong>, Ð\92аÑ\88е измене Ñ\9bе биÑ\82и пÑ\80ипиÑ\81иване Ð\92аÑ\88ем коÑ\80иÑ\81ниÑ\87ком именÑ\83, поÑ\80ед дÑ\80Ñ\83гиÑ\85 погодноÑ\81Ñ\82и.",
"anonpreviewwarning": "<em>Нисте пријављени. Ако објавите страницу, Ваша IP адреса ће бити јавно видљива у њеној историји измена и другде.</em>",
"missingsummary": "<strong>Подсетник:</strong> Нисте унели опис измене.\nАко поново кликнете на „$1”, Ваша измена ће бити сачувана без описа.",
"selfredirect": "<strong>Упозорење:</strong> Преусмеравате ову страницу на њу саму.\nМожда вам је одредишна страница за преусмерење погрешна или уређујете погрешну страницу.\nАко још једном притиснете „$1”, преусмерење ће свеједно бити направљено.",
"newarticle": "(нови)",
"newarticletext": "Дошли сте на страницу која још не постоји.\nДа бисте је направили, почните да куцате у прозор испод овог текста (погледајте [$1 страницу за помоћ]).\nАко сте овде дошли грешком, вратите се на претходну страницу.",
"anontalkpagetext": "----\n<em>Ово је страница за разговор с анонимним корисником који још нема налог или га не користи.</em>\nЗбог тога морамо да користимо бројчану IP адресу како бисмо га препознали.\nТакву адресу може делити више корисника.\nАко сте анонимни корисник и мислите да су вам упућене примедбе, [[Special:CreateAccount|отворите налог]] или се [[Special:UserLogin|пријавите]] да бисте избегли будућу забуну с осталим анонимним корисницима.",
- "noarticletext": "Ð\9dа овоÑ\98 Ñ\81Ñ\82Ñ\80аниÑ\86и Ñ\82Ñ\80енÑ\83Ñ\82но нема Ñ\81адÑ\80жаÑ\98а.\nМожете [[Special:Search/{{PAGENAME}}|потражити овај наслов]] на другим страницама,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} претражити сродне извештаје] или [{{fullurl:{{FULLPAGENAME}}|action=edit}} направити ову страницу]</span>.",
- "noarticletext-nopermission": "Ð\9dа овоÑ\98 Ñ\81Ñ\82Ñ\80аниÑ\86и Ñ\82Ñ\80енÑ\83Ñ\82но нема Ñ\81адÑ\80жаÑ\98а.\nМожете [[Special:Search/{{PAGENAME}}|потражити овај наслов]] на другим страницама или <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} претражити сродне дневнике]</span>, али немате дозволу да направите ову страницу.",
+ "noarticletext": "Ð\9dа овоÑ\98 Ñ\81Ñ\82Ñ\80аниÑ\86и Ñ\82Ñ\80енÑ\83Ñ\82но нема Ñ\82екÑ\81Ñ\82а.\nМожете [[Special:Search/{{PAGENAME}}|потражити овај наслов]] на другим страницама,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} претражити сродне извештаје] или [{{fullurl:{{FULLPAGENAME}}|action=edit}} направити ову страницу]</span>.",
+ "noarticletext-nopermission": "Ð\9dа овоÑ\98 Ñ\81Ñ\82Ñ\80аниÑ\86и Ñ\82Ñ\80енÑ\83Ñ\82но нема Ñ\82екÑ\81Ñ\82а.\nМожете [[Special:Search/{{PAGENAME}}|потражити овај наслов]] на другим страницама или <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} претражити сродне дневнике]</span>, али немате дозволу да направите ову страницу.",
"missing-revision": "Не могу да пронађем измену бр. $1 на страници под називом „{{FULLPAGENAME}}“.\n\nОво се обично дешава када пратите застарелу везу до странице која је обрисана.\nВише информација можете пронаћи у [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} дневнику брисања].",
"userpage-userdoesnotexist": "Кориснички налог „<nowiki>$1</nowiki>“ није отворен.\nРазмислите да ли заиста желите да направите/уредите ову страницу.",
"userpage-userdoesnotexist-view": "Кориснички налог „$1“ није отворен.",
"viewpagelogs": "Дневници ове странице",
"nohistory": "Не постоји историја измена ове странице.",
"currentrev": "Тренутна измена",
- "currentrev-asof": "Ð\9fоÑ\81ледÑ\9aа измена на датум $2 у $3",
+ "currentrev-asof": "ТÑ\80енÑ\83Ñ\82на измена на датум $2 у $3",
"revisionasof": "Измена на датум $2 у $3",
"revision-info": "Измена од $1 од стране {{GENDER:$6|корисника $2|кориснице $2}}$7",
"previousrevision": "← Старија измена",
"next-page": "следећа страница",
"prevn-title": "$1 {{PLURAL:$1|претходни резултат|претходна резултата|претходних резултата}}",
"nextn-title": "$1 {{PLURAL:$1|следећи резултат|следећа резултата|следећих резултата}}",
- "shown-title": "Прикажи $1 {{PLURAL:$1|резултат|резултата|резултата}} по страници",
+ "shown-title": "Прикажи $1 {{PLURAL:$1|резултат|резултата}} по страници",
"viewprevnext": "Погледај ($1 {{int:pipe-separator}} $2) ($3).",
"searchmenu-exists": "<strong>Постоји страница под називом „[[:$1]]”!</strong> {{PLURAL:$2|0=|Такође погледајте друге пронађене резултате претраге.}}",
- "searchmenu-new": "<strong>Направите страницу „[[:$1]]”!</strong> {{PLURAL:$2|0=|Такође погледајте резултат претраге.|Такође погледајте резултате претраге.}}",
+ "searchmenu-new": "<strong>Направите страницу „[[:$1]]” на овом викију!</strong> {{PLURAL:$2|0=|Такође погледајте страницу пронађену претрагом.|Такође погледајте резултате претраге.}}",
"searchprofile-articles": "Странице са садржајем",
"searchprofile-images": "Датотеке",
"searchprofile-everything": "Све",
"searchprofile-images-tooltip": "Претражите датотеке",
"searchprofile-everything-tooltip": "Претражите сав садржај (укључујући странице за разговор)",
"searchprofile-advanced-tooltip": "Претражите прилагођене именске просторе",
- "search-result-size": "$1 ({{PLURAL:$2|1 реч|$2 речи|$2 речи}})",
+ "search-result-size": "$1 ({{PLURAL:$2|1 реч|$2 речи}})",
"search-result-category-size": "{{PLURAL:$1|1 члан|$1 члана|$1 чланова}}, ({{PLURAL:$2|1 поткатегорија|$2 поткатегорије|$2 поткатегорија}}, {{PLURAL:$3|1 датотека|$3 датотеке|$3 датотека}})",
- "search-redirect": "(преусмерено са $1)",
+ "search-redirect": "(преусмерење са $1)",
"search-section": "(одељак $1)",
"search-category": "(категорија $1)",
"search-file-match": "(подудара се садржај датотеке)",
- "search-suggest": "Да ли сте мислили на: $1",
+ "search-suggest": "Да ли сте мислили: $1",
"search-rewritten": "Приказани резултати за $1. Ипак претражи $2.",
"search-interwiki-caption": "Резултати са сестринских пројеката",
"search-interwiki-default": "Резултати са $1:",
"showingresults": "Испод {{PLURAL:$1|је приказан <strong>1</strong> резултат|су приказана <strong>$1</strong> резултата|је приказано <strong>$1</strong> резултата}}, почев од броја <strong>$2</strong>.",
"showingresultsinrange": "Испод {{PLURAL:$1|је приказан <strong>1</strong> резултат|су приказана <strong>$1</strong> резултата|је приказано <strong>$1</strong> резултата}}, у распону од <strong>$2</strong> до <strong>$3</strong>.",
"search-showingresults": "{{PLURAL:$4|Резултат <strong>$1</strong> од <strong>$3</strong>|Резултати <strong>$1—$2</strong> од <strong>$3</strong>}}",
- "search-nonefound": "Ð\9dема поклапаÑ\9aа.",
+ "search-nonefound": "Ð\9dиÑ\81Ñ\83 пÑ\80онаÑ\92ени Ñ\80езÑ\83лÑ\82аÑ\82и коÑ\98и одговаÑ\80аÑ\98Ñ\83 Ñ\83пиÑ\82Ñ\83.",
"search-nonefound-thiswiki": "Нема резултата на овом сајту који се поклапају са термином претраге.",
"powersearch-legend": "Напредна претрага",
"powersearch-ns": "Претрага по именским просторима:",
"right-bot": "сматрање измена као аутоматски процес",
"right-nominornewtalk": "непоседовање мањих измена на страницама за разговор отвара прозор за нове поруке",
"right-apihighlimits": "коришћење виших граница за упите из API-ја",
- "right-writeapi": "пиÑ\81аÑ\9aе API-ја",
+ "right-writeapi": "могÑ\83Ñ\9bноÑ\81Ñ\82 пиÑ\81аÑ\9aа API-ја",
"right-delete": "брисање страница",
"right-bigdelete": "брисање страница с великом историјом",
"right-deletelogentry": "брисање и враћање одређених ставки у дневнику",
"recentchanges-label-plusminus": "Промена величине странице у бајтовима",
"recentchanges-legend-heading": "<strong>Легенда:</strong>",
"recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (такође погледајте [[Special:NewPages|списак нових страница]])",
+ "recentchanges-legend-plusminus": "(<em>±123</em>)",
"recentchanges-submit": "Прикажи",
"rcfilters-tag-remove": "Уклоните филтер „$1“",
"rcfilters-legend-heading": "<strong>Списак скраћеница:</strong>",
"rcfilters-target-page-placeholder": "Унесите име странице (или категорије)",
"rcnotefrom": "Испод {{PLURAL:$5|је измена|су измене}} од <strong>$3, $4</strong> (до <strong>$1</strong> приказано).",
"rclistfromreset": "Ресетуј одабир датума",
- "rclistfrom": "Прикажи нове измене почев од $2, $3",
+ "rclistfrom": "Прикажи нове измене почев од $3 у $2",
"rcshowhideminor": "$1 мање измене",
"rcshowhideminor-show": "Прикажи",
"rcshowhideminor-hide": "Сакриј",
"recentchangeslinked-feed": "Сродне измене",
"recentchangeslinked-toolbox": "Сродне измене",
"recentchangeslinked-title": "Сродне измене са „$1“",
- "recentchangeslinked-summary": "УнеÑ\81иÑ\82е име Ñ\81Ñ\82Ñ\80аниÑ\86е да биÑ\81Ñ\82е видели пÑ\80омене на Ñ\81Ñ\82Ñ\80аниÑ\86ама коÑ\98е Ñ\81Ñ\83 повезане Ñ\81а или Ñ\81а Ñ\82е Ñ\81Ñ\82Ñ\80аниÑ\86е. (Ð\94а биÑ\81Ñ\82е видели Ñ\87ланове каÑ\82егоÑ\80иÑ\98е, Ñ\83неÑ\81иÑ\82е {{ns:category}}:Ð\98ме каÑ\82егоÑ\80иÑ\98е). Ð\9fÑ\80омене на Ñ\81Ñ\82Ñ\80аниÑ\86ама коÑ\98е Ñ\81Ñ\83 на [[Special:Watchlist|Вашем списку надгледања]] су <strong>подебљане</strong>.",
+ "recentchangeslinked-summary": "УнеÑ\81иÑ\82е име Ñ\81Ñ\82Ñ\80аниÑ\86е да биÑ\81Ñ\82е видели измене Ñ\81Ñ\82Ñ\80аниÑ\86а коÑ\98е Ñ\81Ñ\83 повезане Ñ\81а или Ñ\81а Ñ\82е Ñ\81Ñ\82Ñ\80аниÑ\86е. (Ð\94а биÑ\81Ñ\82е видели Ñ\87ланове каÑ\82егоÑ\80иÑ\98е, Ñ\83неÑ\81иÑ\82е {{ns:category}}:Ð\98ме каÑ\82егоÑ\80иÑ\98е). Ð\98змене Ñ\81Ñ\82Ñ\80аниÑ\86а на [[Special:Watchlist|Вашем списку надгледања]] су <strong>подебљане</strong>.",
"recentchangeslinked-page": "Назив странице:",
"recentchangeslinked-to": "Прикажи измене страница које су повезане с датом страницом",
"recentchanges-page-added-to-category": "[[:$1]] је додата у категорију",
"upload-curl-error28": "Отпремање је истекло",
"upload-curl-error28-text": "Сервер не одговара на упит.\nПроверите да ли сајт ради, мало осачекајте и покушајте поново.\nПробајте касније када буде мање оптерећење.",
"license": "Лиценца:",
- "license-header": "Ð\9bиÑ\86енÑ\86а:",
+ "license-header": "Ð\9bиÑ\86енÑ\86иÑ\80аÑ\9aе",
"nolicense": "Није изабрано",
"licenses-edit": "Уреди избор лиценци",
"license-nopreview": "(преглед није доступан)",
"apisandbox-multivalue-all-namespaces": "$1 (сви именски простори)",
"apisandbox-multivalue-all-values": "$1 (све вредности)",
"booksources": "Штампани извори",
- "booksources-search-legend": "ТÑ\80ажи кÑ\9aижевне изворе",
+ "booksources-search-legend": "Ð\9fÑ\80еÑ\82Ñ\80ажи Ñ\88Ñ\82ампане изворе",
"booksources-isbn": "ISBN:",
"booksources-search": "Претражи",
"booksources-text": "Испод се налази списак веза ка сајтовима који се баве продајом нових и половних књига, а који би могли имати додатне податке о књигама које тражите:",
"watchnologin": "Нисте пријављени",
"addwatch": "Додај на списак надгледања",
"addedwatchtext": "Страница „[[:$1]]“ и њена страница за разговор је додата на Ваш [[Special:Watchlist|списак надгледања]].",
+ "addedwatchtext-talk": "Страница „[[:$1]]” и њена придружена страница је додата на Ваш [[Special:Watchlist|списак надгледања]]",
"addedwatchtext-short": "Страница „$1“ је додата на Ваш списак надгледања.",
"removewatch": "Уклони са списка надгледања",
- "removedwatchtext": "Страница „[[:$1]]“ и њена страница за разговор је уклоњена с вашег [[Special:Watchlist|списка надгледања]].",
+ "removedwatchtext": "Страница „[[:$1]]“ и њена страница за разговор је уклоњена са Вашег [[Special:Watchlist|списка надгледања]].",
"removedwatchtext-short": "Страница „$1“ је уклоњена с вашег списка надгледања.",
"watch": "Надгледај",
"watchthispage": "Надгледај ову страницу",
"wlshowhidemine": "моје измене",
"wlshowhidecategorization": "категоризацију страница",
"watchlist-options": "Опције списка надгледања",
- "watching": "Надгледање…",
- "unwatching": "УклаÑ\9aаÑ\9aе Ñ\81а Ñ\81пиÑ\81ка надгледаÑ\9aа...",
+ "watching": "Надгледам…",
+ "unwatching": "Ð\9fÑ\80еÑ\81Ñ\82аÑ\98ем да надгледам...",
"watcherrortext": "Дошло је до грешке при промени поставки вашег списка надгледања за „$1“.",
"enotif_reset": "Означи све странице као посећене",
"enotif_impersonal_salutation": "{{SITENAME}} корисник",
"dellogpage": "Дневник брисања",
"dellogpagetext": "Испод је списак последњих брисања.",
"deletionlog": "дневник брисања",
- "logentry-create-create": "$1 {{GENDER:$2|је направио|је направила}} страницу $3",
+ "logentry-create-create": "$1 је {{GENDER:$2|направио|направила}} страницу $3",
"reverted": "Враћено на ранију измену",
"deletecomment": "Разлог:",
"deleteotherreason": "Други/додатни разлог:",
"logentry-contentmodel-change-revert": "врати",
"protectlogpage": "Дневник заштите",
"protectlogtext": "Испод је списак заштићених страница.\nПогледајте [[Special:ProtectedPages|списак заштићених страница]] за више детаља.",
- "protectedarticle": "је заштитио „[[$1]]“",
- "modifiedarticleprotection": "промењен степен заштите за „[[$1]]“",
+ "protectedarticle": "је {{GENDER:|заштитио|заштитила}} страницу „[[$1]]“",
+ "modifiedarticleprotection": "је {{GENDER:|променио|променила}} степен заштите странице „[[$1]]“",
"unprotectedarticle": "је скинуо заштиту са странице „[[$1]]“",
"movedarticleprotection": "је преместио подешавања заштите са „[[$2]]“ на „[[$1]]“",
"protectedarticle-comment": "{{GENDER:$2|Заштићена}} страница [[$1]]",
"contribsub2": "За {{GENDER:$3|$1}} ($2)",
"contributions-userdoesnotexist": "Кориснички налог „$1“ није отворен.",
"nocontribs": "Нема измена које одговарају наведеним критеријумима.",
- "uctop": "(последња)",
+ "uctop": "(тренутна)",
"month": "од месеца (и раније):",
"year": "од године (и раније):",
"sp-contributions-newbies": "Прикажи само доприносе нових корисника",
"blocklogpage": "Дневник блокирања",
"blocklog-showlog": "{{GENDER:$1|Овај корисник је раније блокиран|Ова корисница је раније блокирана}}.\nИсторија блокирања се налази испод:",
"blocklog-showsuppresslog": "{{GENDER:$1|Овај корисник је раније блокиран и сакривен|Ова корисница је раније блокирана и сакривена}}.\nИсторија сакривања се налази испод:",
- "blocklogentry": "је блокирао [[$1]] с роком истицања од $2 $3",
- "reblock-logentry": "{{GENDER:|је променио|је променила|је променио}} подешавања за блокирање {{GENDER:$1|корисника|кориснице|корисника}} [[$1]] с роком истека од $2 ($3)",
+ "blocklogentry": "је блокирао [[$1]] са временом истицања од $2 $3",
+ "reblock-logentry": "{{GENDER:|је променио|је променила}} подешавања за блокирање {{GENDER:$1|корисника|кориснице}} [[$1]] са временом истека од $2 ($3)",
"blocklogtext": "Ово је дневник блокирања и деблокирања корисника.\nАутоматски блокиране ИП адресе нису наведене.\nТекуће забране и блокирања можете наћи [[Special:BlockList|овде]].",
"unblocklogentry": "је деблокирао $1",
"block-log-flags-anononly": "само анонимни корисници",
"tooltip-pt-login-private": "Морате да се пријавите да бисте користили овај Вики",
"tooltip-pt-logout": "Одјавите се",
"tooltip-pt-createaccount": "Предлажемо Вам да отворите налог и пријавите се, иако то није обавезно",
- "tooltip-ca-talk": "Разговор о садржају",
+ "tooltip-ca-talk": "Разговор о страници са садржајем",
"tooltip-ca-edit": "Уредите ову страницу",
"tooltip-ca-addsection": "Започните нови одељак",
"tooltip-ca-viewsource": "Ова страница је закључана. \nМожете да погледате њен изворни кôд",
"tooltip-ca-delete": "Обришите ову страницу",
"tooltip-ca-undelete": "Врати измене направљене на овој страници пре него што буде обрисана",
"tooltip-ca-move": "Премести ову страницу",
- "tooltip-ca-watch": "Додајте ову страницу на списак надгледања",
+ "tooltip-ca-watch": "Ð\94одаÑ\98Ñ\82е овÑ\83 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83 на Ñ\81воÑ\98 Ñ\81пиÑ\81ак надгледаÑ\9aа",
"tooltip-ca-unwatch": "Уклоните ову страницу са списка надгледања",
"tooltip-search": "Претражите пројекат {{SITENAME}}",
"tooltip-search-go": "Идите на страницу са тачно овим именом ако постоји",
"tooltip-n-mainpage": "Посетите главну страну",
"tooltip-n-mainpage-description": "Посетите главну страну",
"tooltip-n-portal": "О пројекту, шта можете да радите и где да пронађете ствари",
- "tooltip-n-currentevents": "Пронађите додатне информације о тренутним догађајима",
+ "tooltip-n-currentevents": "Пронађите додатне информације о актуелностима",
"tooltip-n-recentchanges": "Списак скорашњих измена на викију",
"tooltip-n-randompage": "Учитајте случајну страницу",
"tooltip-n-help": "Место где можете да научите нешто",
"tooltip-t-permalink": "Трајна веза ка овој измени странице",
"tooltip-ca-nstab-main": "Погледајте страницу са садржајем",
"tooltip-ca-nstab-user": "Погледајте корисничку страницу",
- "tooltip-ca-nstab-media": "Погледајте мултимедијалну датотеку",
+ "tooltip-ca-nstab-media": "Погледајте медијску страницу",
"tooltip-ca-nstab-special": "Ово је посебна страница. Не можете је мењати.",
"tooltip-ca-nstab-project": "Погледајте страницу пројекта",
- "tooltip-ca-nstab-image": "Прикажи страницу датотеке",
+ "tooltip-ca-nstab-image": "Погледајте страницу датотеке",
"tooltip-ca-nstab-mediawiki": "Погледајте системску поруку",
"tooltip-ca-nstab-template": "Погледајте шаблон",
"tooltip-ca-nstab-help": "Погледајте страницу за помоћ",
- "tooltip-ca-nstab-category": "Ð\9fогледаÑ\98Ñ\82е Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83 каÑ\82егоÑ\80иÑ\98а",
+ "tooltip-ca-nstab-category": "Ð\9fогледаÑ\98Ñ\82е Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83 каÑ\82егоÑ\80иÑ\98е",
"tooltip-minoredit": "Означите као мању измену",
"tooltip-save": "Сачувајте своје измене",
"tooltip-publish": "Објавите своје измене",
"tooltip-preview": "Прегледајте своје измене. Користите ово дугме пре чувања.",
- "tooltip-diff": "Погледајте које измене сте направили на тексту",
+ "tooltip-diff": "Погледајте које измене сте направили у тексту",
"tooltip-compareselectedversions": "Погледаjте разлике између две изабране измене ове странице.",
"tooltip-watch": "Додајте ову страницу на свој списак надгледања",
"tooltip-watchlistedit-normal-submit": "Уклоните наслове",
"tooltip-watchlistedit-raw-submit": "Ажурирај списак",
"tooltip-recreate": "Поново направите страницу иако је обрисана",
"tooltip-upload": "Започните отпремање",
- "tooltip-rollback": "â\80\9eÐ\92Ñ\80аÑ\82иâ\80\9c вÑ\80аÑ\9bа измене поÑ\81ледÑ\9aег коÑ\80иÑ\81ника једним кликом",
- "tooltip-undo": "Опција „поништи” враћа ову измену и отвара образац за уређивање у претпрегледном моду. Омогућава додавање разлога у опису измене.",
+ "tooltip-rollback": "â\80\9eÐ\92Ñ\80аÑ\82иâ\80\9c вÑ\80аÑ\9bа измене поÑ\81ледÑ\9aег допÑ\80иноÑ\81иоÑ\86а ове Ñ\81Ñ\82Ñ\80аниÑ\86е једним кликом",
+ "tooltip-undo": "„Поништи” враћа ову измену и отвара образац за уређивање у претпрегледном моду. Дозвољава додавање разлога у опису измене.",
"tooltip-preferences-save": "Сачувај подешавања",
"tooltip-summary": "Унесите кратак опис",
"interlanguage-link-title": "$1 — $2",
"spam_blanking": "Све измене садрже везе до $1. Чистим",
"spam_deleting": "Све измене садрже везе до $1. Бришем",
"simpleantispam-label": "Анти-спам провера. \n<strong>Не</strong> попуњавај ово унутра!",
- "pageinfo-title": "Ð\9fодаÑ\86и о „$1“",
+ "pageinfo-title": "Ð\98нÑ\84оÑ\80маÑ\86иÑ\98е за „$1“",
"pageinfo-not-current": "Нажалост, немогуће је прибавити ове податке за старије измене.",
- "pageinfo-header-basic": "Ð\9eÑ\81новни подаÑ\86и",
+ "pageinfo-header-basic": "Ð\9eÑ\81новне инÑ\84оÑ\80маÑ\86иÑ\98е",
"pageinfo-header-edits": "Историја измена",
"pageinfo-header-restrictions": "Заштита странице",
"pageinfo-header-properties": "Својства странице",
"pageinfo-robot-noindex": "Није дозвољено",
"pageinfo-watchers": "Број надгледача странице",
"pageinfo-visiting-watchers": "Број надгледача странице који су посетили скорашње измене",
- "pageinfo-few-watchers": "Ð\9cаÑ\9aе од $1 {{PLURAL:$1|пÑ\80аÑ\82иоÑ\86а|пÑ\80аÑ\82иоÑ\86а|пÑ\80аÑ\82илаÑ\86а}}",
+ "pageinfo-few-watchers": "Ð\9cаÑ\9aе од $1 {{PLURAL:$1|надгледаÑ\87а}}",
"pageinfo-redirects-name": "Број преусмерења на ову страницу",
"pageinfo-redirects-value": "$1",
- "pageinfo-subpages-name": "Ð\9fодÑ\81Ñ\82Ñ\80аниÑ\86е ове странице",
+ "pageinfo-subpages-name": "Ð\91Ñ\80оÑ\98 подÑ\81Ñ\82Ñ\80аниÑ\86а ове странице",
"pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|преусмерење|преусмерења|преусмерења}}; $3 {{PLURAL:$3|непреусмерење|непреусмерења|непреусмерења}})",
"pageinfo-firstuser": "Аутор странице",
"pageinfo-firsttime": "Датум стварања странице",
"svg-long-desc": "SVG датотека, номинално $1 × $2 пиксела, величина: $3",
"svg-long-desc-animated": "Анимирана SVG датотека, номинално: $1 × $2 пиксела, величина: $3",
"svg-long-error": "Неисправна SVG датотека: $1",
- "show-big-image": "Ð\9fÑ\83на велиÑ\87ина",
+ "show-big-image": "Ð\98звоÑ\80на даÑ\82оÑ\82ека",
"show-big-image-preview": "Величина овог приказа: $1.",
"show-big-image-preview-differ": "Величина $3 прегледа за ову $2 датотеку је $1.",
"show-big-image-other": "$2 {{PLURAL:$2|друга резолуција|друге резолуције|других резолуција}}: $1.",
"htmlform-title-not-exists": "$1 не постоји.",
"htmlform-user-not-exists": "<strong>$1</strong> не постоји.",
"htmlform-user-not-valid": "<strong>$1</strong> није исправно корисничко име.",
- "logentry-delete-delete": "$1 је {{GENDER:$2|обрисао|обрисала|обрисао}} страницу $3",
+ "logentry-delete-delete": "$1 је {{GENDER:$2|обрисао|обрисала}} страницу $3",
"logentry-delete-delete_redir": "$1 је {{GENDER:$2|обрисао|обрисала}} преусмерење $3 преписивањем",
"logentry-delete-restore": "$1 је {{GENDER:$2|вратио|вратила}} страницу $3 ($4)",
"logentry-delete-restore-nocount": "$1 је {{GENDER:$2|вратио|вратила}} страницу $3",
/**
* Do the actual work. All child classes will need to implement this
*
- * @return bool|null True for success, false for failure. Not returning
+ * @return bool|null|void True for success, false for failure. Not returning
* a value, or returning null, is also interpreted as success. Returning
* false for failure will cause doMaintenance.php to exit the process
* with a non-zero exit status.
$dbw = $this->lbFactory->getMainLB()->getConnection( DB_MASTER );
$sleep = (int)$this->getOption( 'sleep', 10 );
$lastId = 0;
- $this->output( "Starting to add ct_tag_id = {$tagId} for ct_tag = {$tagName}" );
+ $this->output( "Starting to add ct_tag_id = {$tagId} for ct_tag = {$tagName}\n" );
while ( true ) {
// Given that indexes might not be there, it's better to use replica
$ids = $dbr->selectFieldValues(
);
continue;
} else {
- $this->output( "Updating ct_tag_id = {$tagId} up to row ct_id = {$lastId}" );
+ $this->output( "Updating ct_tag_id = {$tagId} up to row ct_id = {$lastId}\n" );
}
$dbw->update(
}
}
- $this->output( "Finished adding ct_tag_id = {$tagId} for ct_tag = {$tagName}" );
+ $this->output( "Finished adding ct_tag_id = {$tagId} for ct_tag = {$tagName}\n" );
}
}
$t0 = microtime( true );
- if ( $wgMultiContentRevisionSchemaMigrationStage < MIGRATION_WRITE_BOTH ) {
+ if ( ( $wgMultiContentRevisionSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) === 0 ) {
$this->writeln(
- "...cannot update while \$wgMultiContentRevisionSchemaMigrationStage < MIGRATION_WRITE_BOTH"
+ '...cannot update while \$wgMultiContentRevisionSchemaMigrationStage '
+ . 'does not have the SCHEMA_COMPAT_WRITE_NEW bit set.'
);
return false;
}
'MediaWiki\Tests\Storage\McrSchemaDetection' => "$testDir/phpunit/includes/Storage/McrSchemaDetection.php",
'MediaWiki\Tests\Storage\McrSchemaOverride' => "$testDir/phpunit/includes/Storage/McrSchemaOverride.php",
'MediaWiki\Tests\Storage\McrWriteBothSchemaOverride' => "$testDir/phpunit/includes/Storage/McrWriteBothSchemaOverride.php",
+ 'MediaWiki\Tests\Storage\McrReadNewSchemaOverride' => "$testDir/phpunit/includes/Storage/McrReadNewSchemaOverride.php",
'MediaWiki\Tests\Storage\RevisionSlotsTest' => "$testDir/phpunit/includes/Storage/RevisionSlotsTest.php",
'MediaWiki\Tests\Storage\RevisionRecordTests' => "$testDir/phpunit/includes/Storage/RevisionRecordTests.php",
'MediaWiki\Tests\Storage\RevisionStoreDbTestBase' => "$testDir/phpunit/includes/Storage/RevisionStoreDbTestBase.php",
}
$stages = [
- MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_NEW ],
- MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_NEW ],
- MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
- MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
+ MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW ],
+ MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW,
+ MIGRATION_NEW ],
+ MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
+ MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
];
$nameKey = $key . '_text';
$actorKey = $key === 'ipb_by' ? 'ipb_by_actor' : substr( $key, 0, -5 ) . '_actor';
- foreach ( $stages as $writeStage => $readRange ) {
+ foreach ( $stages as $writeStage => $possibleReadStages ) {
if ( $key === 'ipb_by' ) {
$extraFields['ipb_address'] = __CLASS__ . "#$writeStage";
}
$callback( $id, $extraFields );
}
- for ( $readStage = $readRange[0]; $readStage <= $readRange[1]; $readStage++ ) {
+ foreach ( $possibleReadStages as $readStage ) {
$r = $this->makeMigration( $readStage );
$queryInfo = $r->getJoin( $key );
];
$stages = [
- MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_NEW ],
- MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_NEW ],
- MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
- MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
+ MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW ],
+ MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW,
+ MIGRATION_NEW ],
+ MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
+ MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
];
- foreach ( $stages as $writeStage => $readRange ) {
+ foreach ( $stages as $writeStage => $possibleReadStages ) {
if ( $key === 'ipb_reason' ) {
$extraFields['ipb_address'] = __CLASS__ . "#$writeStage";
}
$callback( $id );
}
- for ( $readStage = $readRange[0]; $readStage <= $readRange[1]; $readStage++ ) {
+ foreach ( $possibleReadStages as $readStage ) {
$rstore = $this->makeStore( $readStage );
$fieldRow = $this->db->selectRow(
];
$stages = [
- MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_NEW ],
- MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_NEW ],
- MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
- MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
+ MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW ],
+ MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW,
+ MIGRATION_NEW ],
+ MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
+ MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
];
- foreach ( $stages as $writeStage => $readRange ) {
+ foreach ( $stages as $writeStage => $possibleReadStages ) {
if ( $key === 'ipb_reason' ) {
$extraFields['ipb_address'] = __CLASS__ . "#$writeStage";
}
$callback( $id );
}
- for ( $readStage = $readRange[0]; $readStage <= $readRange[1]; $readStage++ ) {
+ foreach ( $possibleReadStages as $readStage ) {
$rstore = $this->makeStoreWithKey( $readStage, $key );
$fieldRow = $this->db->selectRow(
use MediaWiki\Storage\RevisionFactory;
use MediaWiki\Storage\RevisionLookup;
use MediaWiki\Storage\RevisionStore;
-use MediaWiki\Storage\RevisionStoreFactory;
use MediaWiki\Storage\SqlBlobStore;
/**
'BlobStore' => [ 'BlobStore', BlobStore::class ],
'_SqlBlobStore' => [ '_SqlBlobStore', SqlBlobStore::class ],
'RevisionStore' => [ 'RevisionStore', RevisionStore::class ],
- 'RevisionStoreFactory' => [ 'RevisionStoreFactory', RevisionStoreFactory::class ],
'RevisionLookup' => [ 'RevisionLookup', RevisionLookup::class ],
'RevisionFactory' => [ 'RevisionFactory', RevisionFactory::class ],
'ContentModelStore' => [ 'ContentModelStore', NameTableStore::class ],
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
$this->setMwGlobals( 'wgActorTableSchemaMigrationStage', MIGRATION_OLD );
+ $this->setMwGlobals( 'wgMultiContentRevisionSchemaMigrationStage', SCHEMA_COMPAT_OLD );
$this->overrideMwServices();
// First create our dummy page
*/
public function testListRevisions() {
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
+ $this->setMwGlobals( 'wgMultiContentRevisionSchemaMigrationStage', SCHEMA_COMPAT_OLD );
$this->overrideMwServices();
$revisions = $this->archivedPage->listRevisions();
--- /dev/null
+<?php
+use MediaWiki\Tests\Storage\McrReadNewSchemaOverride;
+
+/**
+ * Tests Revision against the intermediate MCR DB schema for use during schema migration.
+ *
+ * @covers Revision
+ *
+ * @group Revision
+ * @group Storage
+ * @group ContentHandler
+ * @group Database
+ * @group medium
+ */
+class RevisionMcrReadNewDbTest extends RevisionDbTestBase {
+
+ use McrReadNewSchemaOverride;
+
+ protected function getContentHandlerUseDB() {
+ return true;
+ }
+
+}
--- /dev/null
+<?php
+namespace MediaWiki\Tests\Storage;
+
+use CommentStoreComment;
+use MediaWiki\MediaWikiServices;
+use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Storage\SlotRecord;
+use TextContent;
+use Title;
+use WikitextContent;
+
+/**
+ * Tests RevisionStore against the intermediate MCR DB schema for use during schema migration.
+ *
+ * @covers \MediaWiki\Storage\RevisionStore
+ *
+ * @group RevisionStore
+ * @group Storage
+ * @group Database
+ * @group medium
+ */
+class McrReadNewRevisionStoreDbTest extends RevisionStoreDbTestBase {
+
+ use McrReadNewSchemaOverride;
+
+ protected function assertRevisionExistsInDatabase( RevisionRecord $rev ) {
+ $numberOfSlots = count( $rev->getSlotRoles() );
+
+ // new schema is written
+ $this->assertSelect(
+ 'slots',
+ [ 'count(*)' ],
+ [ 'slot_revision_id' => $rev->getId() ],
+ [ [ (string)$numberOfSlots ] ]
+ );
+
+ $store = MediaWikiServices::getInstance()->getRevisionStore();
+ $revQuery = $store->getSlotsQueryInfo( [ 'content' ] );
+
+ $this->assertSelect(
+ $revQuery['tables'],
+ [ 'count(*)' ],
+ [
+ 'slot_revision_id' => $rev->getId(),
+ ],
+ [ [ (string)$numberOfSlots ] ],
+ [],
+ $revQuery['joins']
+ );
+
+ // Legacy schema is still being written
+ $this->assertSelect(
+ [ 'revision', 'text' ],
+ [ 'count(*)' ],
+ [ 'rev_id' => $rev->getId(), 'rev_text_id > 0' ],
+ [ [ 1 ] ],
+ [],
+ [ 'text' => [ 'INNER JOIN', [ 'rev_text_id = old_id' ] ] ]
+ );
+
+ parent::assertRevisionExistsInDatabase( $rev );
+ }
+
+ /**
+ * @param SlotRecord $a
+ * @param SlotRecord $b
+ */
+ protected function assertSameSlotContent( SlotRecord $a, SlotRecord $b ) {
+ parent::assertSameSlotContent( $a, $b );
+
+ // Assert that the same content ID has been used
+ $this->assertSame( $a->getContentId(), $b->getContentId() );
+ }
+
+ public function provideInsertRevisionOn_successes() {
+ foreach ( parent::provideInsertRevisionOn_successes() as $case ) {
+ yield $case;
+ }
+
+ yield 'Multi-slot revision insertion' => [
+ [
+ 'content' => [
+ 'main' => new WikitextContent( 'Chicken' ),
+ 'aux' => new TextContent( 'Egg' ),
+ ],
+ 'page' => true,
+ 'comment' => $this->getRandomCommentStoreComment(),
+ 'timestamp' => '20171117010101',
+ 'user' => true,
+ ],
+ ];
+ }
+
+ public function provideNewNullRevision() {
+ foreach ( parent::provideNewNullRevision() as $case ) {
+ yield $case;
+ }
+
+ yield [
+ Title::newFromText( 'UTPage_notAutoCreated' ),
+ [
+ 'content' => [
+ 'main' => new WikitextContent( 'Chicken' ),
+ 'aux' => new WikitextContent( 'Omelet' ),
+ ],
+ ],
+ CommentStoreComment::newUnsavedComment( __METHOD__ . ' comment multi' ),
+ ];
+ }
+
+ public function testGetQueryInfo_NoSlotDataJoin() {
+ $store = MediaWikiServices::getInstance()->getRevisionStore();
+ $queryInfo = $store->getQueryInfo();
+
+ // with the new schema enabled, query info should not join the main slot info
+ $this->assertFalse( array_key_exists( 'a_slot_data', $queryInfo['tables'] ) );
+ $this->assertFalse( array_key_exists( 'a_slot_data', $queryInfo['joins'] ) );
+ }
+
+ public function provideGetArchiveQueryInfo() {
+ yield [
+ [
+ 'tables' => [
+ 'archive',
+ ],
+ 'fields' => array_merge(
+ $this->getDefaultArchiveFields( false ),
+ [
+ 'ar_comment_text' => 'ar_comment',
+ 'ar_comment_data' => 'NULL',
+ 'ar_comment_cid' => 'NULL',
+ 'ar_user_text' => 'ar_user_text',
+ 'ar_user' => 'ar_user',
+ 'ar_actor' => 'NULL',
+ ]
+ ),
+ 'joins' => [
+ ],
+ ]
+ ];
+ }
+
+ public function provideGetQueryInfo() {
+ // TODO: more option variations
+ yield [
+ [ 'page', 'user' ],
+ [
+ 'tables' => [
+ 'revision',
+ 'page',
+ 'user',
+ ],
+ 'fields' => array_merge(
+ $this->getDefaultQueryFields( false ),
+ $this->getCommentQueryFields(),
+ $this->getActorQueryFields(),
+ [
+ 'page_namespace',
+ 'page_title',
+ 'page_id',
+ 'page_latest',
+ 'page_is_redirect',
+ 'page_len',
+ 'user_name',
+ ]
+ ),
+ 'joins' => [
+ 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
+ 'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
+ ],
+ ]
+ ];
+ }
+
+ public function provideGetSlotsQueryInfo() {
+ yield [
+ [],
+ [
+ 'tables' => [
+ 'slots',
+ 'slot_roles',
+ ],
+ 'fields' => array_merge(
+ [
+ 'slot_revision_id',
+ 'slot_content_id',
+ 'slot_origin',
+ 'role_name',
+ ]
+ ),
+ 'joins' => [
+ 'slot_roles' => [ 'INNER JOIN', [ 'slot_role_id = role_id' ] ],
+ ],
+ ]
+ ];
+ yield [
+ [ 'content' ],
+ [
+ 'tables' => [
+ 'slots',
+ 'slot_roles',
+ 'content',
+ 'content_models',
+ ],
+ 'fields' => array_merge(
+ [
+ 'slot_revision_id',
+ 'slot_content_id',
+ 'slot_origin',
+ 'role_name',
+ 'content_size',
+ 'content_sha1',
+ 'content_address',
+ 'model_name',
+ ]
+ ),
+ 'joins' => [
+ 'slot_roles' => [ 'INNER JOIN', [ 'slot_role_id = role_id' ] ],
+ 'content' => [ 'INNER JOIN', [ 'slot_content_id = content_id' ] ],
+ 'content_models' => [ 'INNER JOIN', [ 'content_model = model_id' ] ],
+ ],
+ ]
+ ];
+ }
+
+ public function provideNewMutableRevisionFromArray() {
+ foreach ( parent::provideNewMutableRevisionFromArray() as $case ) {
+ yield $case;
+ }
+
+ yield 'Basic array, multiple roles' => [
+ [
+ 'id' => 2,
+ 'page' => 1,
+ 'timestamp' => '20171017114835',
+ 'user_text' => '111.0.1.2',
+ 'user' => 0,
+ 'minor_edit' => false,
+ 'deleted' => 0,
+ 'len' => 29,
+ 'parent_id' => 1,
+ 'sha1' => '89qs83keq9c9ccw9olvvm4oc9oq50ii',
+ 'comment' => 'Goat Comment!',
+ 'content' => [
+ 'main' => new WikitextContent( 'Söme Cöntent' ),
+ 'aux' => new TextContent( 'Öther Cöntent' ),
+ ]
+ ]
+ ];
+ }
+
+}
--- /dev/null
+<?php
+namespace MediaWiki\Tests\Storage;
+
+use Wikimedia\Rdbms\IMaintainableDatabase;
+use MediaWiki\DB\PatchFileLocation;
+
+/**
+ * Trait providing schema overrides that allow tests to run against the intermediate MCR database
+ * schema for use during schema migration.
+ */
+trait McrReadNewSchemaOverride {
+
+ use PatchFileLocation;
+ use McrSchemaDetection;
+
+ /**
+ * @return int
+ */
+ protected function getMcrMigrationStage() {
+ return SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW;
+ }
+
+ /**
+ * @return string[]
+ */
+ protected function getMcrTablesToReset() {
+ return [ 'content', 'content_models', 'slots', 'slot_roles' ];
+ }
+
+ /**
+ * @override MediaWikiTestCase::getSchemaOverrides
+ * @return array[]
+ */
+ protected function getSchemaOverrides( IMaintainableDatabase $db ) {
+ $overrides = [
+ 'scripts' => [],
+ 'drop' => [],
+ 'create' => [],
+ 'alter' => [],
+ ];
+
+ if ( !$this->hasMcrTables( $db ) ) {
+ $overrides['create'] = [ 'slots', 'content', 'slot_roles', 'content_models', ];
+ $overrides['scripts'][] = $this->getSqlPatchPath( $db, 'patch-slot_roles' );
+ $overrides['scripts'][] = $this->getSqlPatchPath( $db, 'patch-content_models' );
+ $overrides['scripts'][] = $this->getSqlPatchPath( $db, 'patch-content' );
+ $overrides['scripts'][] = $this->getSqlPatchPath( $db, 'patch-slots' );
+ }
+
+ if ( !$this->hasPreMcrFields( $db ) ) {
+ $overrides['alter'][] = 'revision';
+ $overrides['scripts'][] = $this->getSqlPatchPath( $db, 'create-pre-mcr-fields', __DIR__ );
+ }
+
+ return $overrides;
+ }
+
+}
protected function assertRevisionExistsInDatabase( RevisionRecord $rev ) {
$numberOfSlots = count( $rev->getSlotRoles() );
+ // new schema is written
$this->assertSelect(
'slots',
[ 'count(*)' ],
$revQuery['joins']
);
- $this->assertSelect(
- 'content',
- [ 'count(*)' ],
- [ 'content_address' => $rev->getSlot( 'main' )->getAddress() ],
- [ [ 1 ] ]
- );
-
parent::assertRevisionExistsInDatabase( $rev );
}
}
protected function assertRevisionExistsInDatabase( RevisionRecord $rev ) {
+ // New schema is being written
$this->assertSelect(
'slots',
[ 'count(*)' ],
[ [ '1' ] ]
);
+ // Legacy schema is still being written
+ $this->assertSelect(
+ [ 'revision', 'text' ],
+ [ 'count(*)' ],
+ [ 'rev_id' => $rev->getId(), 'rev_text_id > 0' ],
+ [ [ 1 ] ],
+ [],
+ [ 'text' => [ 'INNER JOIN', [ 'rev_text_id = old_id' ] ] ]
+ );
+
parent::assertRevisionExistsInDatabase( $rev );
}
* @return int
*/
protected function getMcrMigrationStage() {
- return MIGRATION_WRITE_BOTH;
+ return SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD;
}
/**
namespace MediaWiki\Tests\Storage;
use InvalidArgumentException;
+use MediaWiki\Storage\RevisionRecord;
use Revision;
use WikitextContent;
return $row;
}
+ protected function assertRevisionExistsInDatabase( RevisionRecord $rev ) {
+ // Legacy schema is still being written
+ $this->assertSelect(
+ [ 'revision', 'text' ],
+ [ 'count(*)' ],
+ [ 'rev_id' => $rev->getId(), 'rev_text_id > 0' ],
+ [ [ 1 ] ],
+ [],
+ [ 'text' => [ 'INNER JOIN', [ 'rev_text_id = old_id' ] ] ]
+ );
+
+ parent::assertRevisionExistsInDatabase( $rev );
+ }
+
public function provideGetArchiveQueryInfo() {
yield [
[
+++ /dev/null
-<?php
-
-namespace MediaWiki\Tests\Storage;
-
-use ActorMigration;
-use CommentStore;
-use MediaWiki\Logger\LoggerFactory;
-use MediaWiki\Storage\NameTableStore;
-use MediaWiki\Storage\RevisionStore;
-use MediaWiki\Storage\RevisionStoreFactory;
-use MediaWiki\Storage\SqlBlobStore;
-use MediaWikiTestCase;
-use WANObjectCache;
-use Wikimedia\Rdbms\LoadBalancer;
-use Wikimedia\TestingAccessWrapper;
-
-class RevisionStoreFactoryTest extends MediaWikiTestCase {
-
- public function testValidConstruction_doesntCauseErrors() {
- new RevisionStoreFactory(
- $this->getMockLoadBalancer(),
- $this->getMockSqlBlobStore(),
- $this->getHashWANObjectCache(),
- $this->getMockCommentStore(),
- $this->getMockNameTableStore(),
- $this->getMockNameTableStore(),
- MIGRATION_OLD,
- ActorMigration::newMigration(),
- LoggerFactory::getInstance( 'someInstance' ),
- true
- );
- $this->assertTrue( true );
- }
-
- public function provideWikiIds() {
- yield [ true ];
- yield [ false ];
- yield [ 'somewiki' ];
- yield [ 'somewiki', MIGRATION_OLD , false ];
- yield [ 'somewiki', MIGRATION_NEW , true ];
- }
-
- /**
- * @dataProvider provideWikiIds
- */
- public function testGetRevisionStore(
- $wikiId,
- $mcrMigrationStage = MIGRATION_OLD,
- $contentHandlerUseDb = true
- ) {
- $lb = $this->getMockLoadBalancer();
- $blobStore = $this->getMockSqlBlobStore();
- $cache = $this->getHashWANObjectCache();
- $commentStore = $this->getMockCommentStore();
- $contentModelStore = $this->getMockNameTableStore();
- $slotRoleStore = $this->getMockNameTableStore();
- $actorMigration = ActorMigration::newMigration();
- $logger = LoggerFactory::getInstance( 'someInstance' );
-
- $factory = new RevisionStoreFactory(
- $lb,
- $blobStore,
- $cache,
- $commentStore,
- $contentModelStore,
- $slotRoleStore,
- $mcrMigrationStage,
- $actorMigration,
- $logger,
- $contentHandlerUseDb
- );
-
- $store = $factory->getRevisionStore( $wikiId );
- $wrapper = TestingAccessWrapper::newFromObject( $store );
-
- // ensure the correct object type is returned
- $this->assertInstanceOf( RevisionStore::class, $store );
-
- // ensure the RevisionStore is for the given wikiId
- $this->assertSame( $wikiId, $wrapper->wikiId );
-
- // ensure all other required services are correctly set
- $this->assertSame( $lb, $wrapper->loadBalancer );
- $this->assertSame( $blobStore, $wrapper->blobStore );
- $this->assertSame( $cache, $wrapper->cache );
- $this->assertSame( $commentStore, $wrapper->commentStore );
- $this->assertSame( $contentModelStore, $wrapper->contentModelStore );
- $this->assertSame( $slotRoleStore, $wrapper->slotRoleStore );
- $this->assertSame( $mcrMigrationStage, $wrapper->mcrMigrationStage );
- $this->assertSame( $actorMigration, $wrapper->actorMigration );
- $this->assertSame( $logger, $wrapper->logger );
- $this->assertSame( $contentHandlerUseDb, $store->getContentHandlerUseDB() );
- }
-
- /**
- * @return \PHPUnit_Framework_MockObject_MockObject|NameTableStore
- */
- private function getMockNameTableStore() {
- return $this->getMockBuilder( NameTableStore::class )
- ->disableOriginalConstructor()->getMock();
- }
-
- /**
- * @return \PHPUnit_Framework_MockObject_MockObject|LoadBalancer
- */
- private function getMockLoadBalancer() {
- return $this->getMockBuilder( LoadBalancer::class )
- ->disableOriginalConstructor()->getMock();
- }
-
- /**
- * @return \PHPUnit_Framework_MockObject_MockObject|SqlBlobStore
- */
- private function getMockSqlBlobStore() {
- return $this->getMockBuilder( SqlBlobStore::class )
- ->disableOriginalConstructor()->getMock();
- }
-
- /**
- * @return \PHPUnit_Framework_MockObject_MockObject|CommentStore
- */
- private function getMockCommentStore() {
- return $this->getMockBuilder( CommentStore::class )
- ->disableOriginalConstructor()->getMock();
- }
-
- private function getHashWANObjectCache() {
- return new WANObjectCache( [ 'cache' => new \HashBagOStuff() ] );
- }
-
-}
public function provideSetContentHandlerUseDB() {
return [
- // ContentHandlerUseDB can be true of false pre migration
- [ false, MIGRATION_OLD, false ],
- [ true, MIGRATION_OLD, false ],
- // During migration it can not be false
- [ false, MIGRATION_WRITE_BOTH, true ],
- // But it can be true
- [ true, MIGRATION_WRITE_BOTH, false ],
+ // ContentHandlerUseDB can be true of false pre migration.
+ [ false, SCHEMA_COMPAT_OLD, false ],
+ [ true, SCHEMA_COMPAT_OLD, false ],
+ // During and after migration it can not be false...
+ [ false, SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, true ],
+ [ false, SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, true ],
+ [ false, SCHEMA_COMPAT_NEW, true ],
+ // ...but it can be true.
+ [ true, SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, false ],
+ [ true, SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, false ],
+ [ true, SCHEMA_COMPAT_NEW, false ],
];
}
public function provideMigrationConstruction() {
return [
- [ MIGRATION_OLD, false ],
- [ MIGRATION_WRITE_BOTH, false ],
+ [ SCHEMA_COMPAT_OLD, false ],
+ [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, false ],
+ [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, false ],
+ [ SCHEMA_COMPAT_NEW, false ],
+ [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_BOTH, true ],
+ [ SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_READ_BOTH, true ],
+ [ SCHEMA_COMPAT_WRITE_NEW | SCHEMA_COMPAT_READ_BOTH, true ],
];
}
--- /dev/null
+<?php
+use MediaWiki\Tests\Storage\McrReadNewSchemaOverride;
+
+/**
+ * Tests WikiPage against the intermediate MCR DB schema for use during schema migration.
+ *
+ * @covers WikiPage
+ *
+ * @group WikiPage
+ * @group Storage
+ * @group ContentHandler
+ * @group Database
+ * @group medium
+ */
+class WikiPageMcrReadNewDbTest extends WikiPageDbTestBase {
+
+ use McrReadNewSchemaOverride;
+
+ protected function getContentHandlerUseDB() {
+ return true;
+ }
+
+}