3 namespace MediaWiki\Tests\Maintenance
;
6 use MediaWiki\Content\WikitextContent
;
7 use MediaWiki\Context\DerivativeContext
;
8 use MediaWiki\Context\RequestContext
;
9 use MediaWiki\MainConfigNames
;
10 use MediaWiki\Revision\RevisionRecord
;
11 use MediaWiki\Revision\SlotRecord
;
12 use MediaWiki\Title\Title
;
13 use MediaWiki\User\User
;
16 use Wikimedia\Rdbms\IDatabase
;
19 * Trait for creating a know set of test pages in the database,
20 * corresponding to the XML data files in tests/phpunit/data/dumps,
21 * to be used used with DumpAsserter::assertDOM().
23 trait PageDumpTestDataTrait
{
25 // We'll add several pages, revision and texts. The following variables hold the
28 // phpcs:ignore MediaWiki.Commenting.PropertyDocumentation.WrongStyle
35 private Title
$pageTitle1;
36 private Title
$pageTitle2;
37 private Title
$pageTitle3;
38 private Title
$pageTitle4;
39 private Title
$pageTitle5;
42 private static $numOfPages = 4;
44 private static $numOfRevs = 8;
46 private RevisionRecord
$rev1_1;
47 private RevisionRecord
$rev2_1;
48 private RevisionRecord
$rev2_2;
49 private RevisionRecord
$rev2_3;
50 private RevisionRecord
$rev2_4;
51 private RevisionRecord
$rev3_1;
52 private RevisionRecord
$rev3_2;
53 private RevisionRecord
$rev4_1;
54 private RevisionRecord
$rev5_1;
56 private int $namespace;
57 private int $talk_namespace;
59 protected function addTestPages( User
$sysopUser ) {
60 // be sure, titles created here using english namespace names
61 $this->setContentLang( 'en' );
64 $this->namespace = $this->getDefaultWikitextNS();
65 $this->talk_namespace
= NS_TALK
;
67 if ( $this->namespace === $this->talk_namespace
) {
68 // @todo work around this.
69 throw new RuntimeException( "The default wikitext namespace is the talk namespace. "
70 . " We can't currently deal with that." );
73 $wikiPageFactory = $this->getServiceContainer()->getWikiPageFactory();
74 $this->pageTitle1
= Title
::makeTitle( $this->namespace, 'BackupDumperTestP1' );
75 $page = $wikiPageFactory->newFromTitle( $this->pageTitle1
);
76 $this->rev1_1
= $this->addMultiSlotRevision(
79 SlotRecord
::MAIN
=> new WikitextContent( 'BackupDumperTestP1Text1' ),
80 'aux' => new WikitextContent( 'BackupDumperTestP1Text1/aux' ),
82 "BackupDumperTestP1Summary1"
84 $this->pageId1
= $page->getId();
86 $this->pageTitle2
= Title
::makeTitle( $this->namespace, 'BackupDumperTestP2' );
87 $page = $wikiPageFactory->newFromTitle( $this->pageTitle2
);
88 [ , , $this->rev2_1
] = $this->addRevision( $page,
89 "BackupDumperTestP2Text1", "BackupDumperTestP2Summary1" );
90 [ , , $this->rev2_2
] = $this->addRevision( $page,
91 "BackupDumperTestP2Text2", "BackupDumperTestP2Summary2" );
92 [ , , $this->rev2_3
] = $this->addRevision( $page,
93 "BackupDumperTestP2Text3", "BackupDumperTestP2Summary3" );
94 [ , , $this->rev2_4
] = $this->addRevision( $page,
95 "BackupDumperTestP2Text4 some additional Text ",
96 "BackupDumperTestP2Summary4 extra " );
97 $this->pageId2
= $page->getId();
99 $context = new DerivativeContext( RequestContext
::getMain() );
100 $context->setUser( $sysopUser );
102 $revDel = RevisionDeleter
::createList(
106 [ $this->rev2_2
->getId() ]
108 $revDel->setVisibility( [
109 'value' => [ RevisionRecord
::DELETED_TEXT
=> 1 ],
110 'comment' => 'testing!'
113 // re-load from database, with correct deletion status
114 $this->rev2_2
= $this->getServiceContainer()->getRevisionLookup()->getRevisionById(
115 $this->rev2_2
->getId()
118 $this->pageTitle3
= Title
::makeTitle( $this->namespace, 'BackupDumperTestP3' );
119 $page = $wikiPageFactory->newFromTitle( $this->pageTitle3
);
120 [ , , $this->rev3_1
] = $this->addRevision( $page,
121 "BackupDumperTestP3Text1", "BackupDumperTestP2Summary1" );
122 [ , , $this->rev3_2
] = $this->addRevision( $page,
123 "BackupDumperTestP3Text2", "BackupDumperTestP2Summary2" );
124 $this->pageId3
= $page->getId();
125 $this->getServiceContainer()->getDeletePageFactory()
126 ->newDeletePage( $page, $context->getAuthority() )
127 ->deleteUnsafe( "Testing" );
129 $this->pageTitle4
= Title
::makeTitle( $this->talk_namespace
, 'BackupDumperTestP1' );
130 $page = $wikiPageFactory->newFromTitle( $this->pageTitle4
);
131 [ , , $this->rev4_1
] = $this->addRevision( $page,
132 "Talk about BackupDumperTestP1 Text1",
133 "Talk BackupDumperTestP1 Summary1" );
134 $this->pageId4
= $page->getId();
136 $this->pageTitle5
= Title
::makeTitle( NS_MAIN
, 'BackupDumperTestP5' );
137 $page = $wikiPageFactory->newFromTitle( $this->pageTitle5
);
138 [ , , $this->rev5_1
] = $this->addRevision( $page,
139 "BackupDumperTestP5 Text1",
140 "BackupDumperTestP5 Summary1" );
141 $this->pageId5
= $page->getId();
143 $this->rev5_1
= $this->corruptRevisionData( $this->getDb(), $this->rev5_1
);
144 } catch ( Exception
$e ) {
145 // We'd love to pass $e directly. However, ... see
146 // documentation of exceptionFromAddDBData in
148 $this->exceptionFromAddDBData
= $e;
151 // Since we will restrict dumping by page ranges (to allow
152 // working tests, even if the db gets prepopulated by a base
153 // class), we have to assert, that the page id are consecutively
156 [ $this->pageId1 +
1, $this->pageId1 +
2, $this->pageId1 +
3 ],
157 [ $this->pageId2
, $this->pageId3
, $this->pageId4
],
158 "Page ids increasing without holes" );
162 * @param string $name
163 * @param string $schemaVersion
165 * @return string path of the dump file
167 protected function getDumpTemplatePath( $name, $schemaVersion ) {
168 return __DIR__
. "/../data/dumps/$name.$schemaVersion.xml";
172 * Corrupt the information about the given revision in the database.
174 * @param IDatabase $db
175 * @param RevisionRecord $revision
177 * @return RevisionRecord
179 protected function corruptRevisionData( IDatabase
$db, RevisionRecord
$revision ) {
180 $db->newUpdateQueryBuilder()
181 ->update( 'content' )
182 ->set( [ 'content_address' => 'tt:0' ] )
183 ->where( [ 'content_id' => $revision->getSlot( SlotRecord
::MAIN
)->getContentId() ] )
186 $revision = $this->getServiceContainer()->getRevisionLookup()->getRevisionById(
193 * Register variables for use with DumpAsserter::assertDOM().
195 * @param string $prefix
196 * @param RevisionRecord $rev
197 * @param DumpAsserter $asserter
199 protected function setRevisionVarMappings( $prefix, RevisionRecord
$rev, DumpAsserter
$asserter ) {
200 $ts = wfTimestamp( TS_ISO_8601
, $rev->getTimestamp() );
201 $title = $this->getServiceContainer()->getTitleFormatter()->getPrefixedText(
202 $rev->getPageAsLinkTarget()
205 $asserter->setVarMapping( $prefix . 'pageid', $rev->getPageId() );
206 $asserter->setVarMapping( $prefix . 'title', $title );
207 $asserter->setVarMapping( $prefix . 'namespace', $rev->getPageAsLinkTarget()->getNamespace() );
209 $asserter->setVarMapping( $prefix . 'id', $rev->getId() );
210 $asserter->setVarMapping( $prefix . 'parentid', $rev->getParentId() );
211 $asserter->setVarMapping( $prefix . 'timestamp', $ts );
212 $asserter->setVarMapping( $prefix . 'sha1', $rev->getSha1() );
213 $asserter->setVarMapping( $prefix . 'username', $rev->getUser()->getName() );
214 $asserter->setVarMapping( $prefix . 'userid', $rev->getUser()->getId() );
215 $asserter->setVarMapping( $prefix . 'comment', $rev->getComment()->text
);
217 foreach ( $rev->getSlotRoles() as $role ) {
218 $slot = $rev->getSlot( $role );
220 $asserter->setVarMapping( $prefix . $role . '_textid', $this->getSlotTextId( $slot ) );
221 $asserter->setVarMapping( $prefix . $role . '_location', $slot->getAddress() );
222 $asserter->setVarMapping( $prefix . $role . '_text', $this->getSlotText( $slot ) );
223 $asserter->setVarMapping( $prefix . $role . '_size', $slot->getSize() );
224 $asserter->setVarMapping( $prefix . $role . '_sha1', $slot->getSha1() );
225 $asserter->setVarMapping( $prefix . $role . '_origin', $slot->getOrigin() );
226 $asserter->setVarMapping( $prefix . $role . '_model', $slot->getModel() );
227 $asserter->setVarMapping( $prefix . $role . '_format', $this->getSlotFormat( $slot ) );
228 $asserter->setVarMapping( $prefix . $role . '_role', $slot->getRole() );
233 * Register variables for use with DumpAsserter::assertDOM().
235 * @param DumpAsserter $asserter
237 protected function setCurrentRevisionsVarMappings( DumpAsserter
$asserter ) {
238 $this->setRevisionVarMappings( 'rev1_1_', $this->rev1_1
, $asserter );
239 $this->setRevisionVarMappings( 'rev2_4_', $this->rev2_4
, $asserter );
240 // skip page 3, since it's deleted
241 $this->setRevisionVarMappings( 'rev4_1_', $this->rev4_1
, $asserter );
242 $this->setRevisionVarMappings( 'rev5_1_', $this->rev5_1
, $asserter );
246 * Register variables for use with DumpAsserter::assertDOM().
248 * @param DumpAsserter $asserter
250 protected function setAllRevisionsVarMappings( DumpAsserter
$asserter ) {
251 $this->setRevisionVarMappings( 'rev1_1_', $this->rev1_1
, $asserter );
252 $this->setRevisionVarMappings( 'rev2_1_', $this->rev2_1
, $asserter );
253 $this->setRevisionVarMappings( 'rev2_2_', $this->rev2_2
, $asserter );
254 $this->setRevisionVarMappings( 'rev2_3_', $this->rev2_3
, $asserter );
255 $this->setRevisionVarMappings( 'rev2_4_', $this->rev2_4
, $asserter );
256 // skip page 3, since it's deleted
257 $this->setRevisionVarMappings( 'rev4_1_', $this->rev4_1
, $asserter );
258 $this->setRevisionVarMappings( 'rev5_1_', $this->rev5_1
, $asserter );
261 private function setSiteVarMappings( DumpAsserter
$asserter ) {
262 $config = $this->getServiceContainer()->getMainConfig();
264 $asserter->setVarMapping( 'mw_version', MW_VERSION
);
265 $asserter->setVarMapping( 'schema_version', $asserter->getSchemaVersion() );
267 $asserter->setVarMapping( 'site_name', $config->get( MainConfigNames
::Sitename
) );
268 $asserter->setVarMapping(
270 $this->getServiceContainer()->getTitleFormatter()->getNamespaceName(
275 $asserter->setVarMapping( 'site_db', $config->get( MainConfigNames
::DBname
) );
276 $asserter->setVarMapping(
278 $config->get( MainConfigNames
::CapitalLinks
) ?
'first-letter' : 'case-sensitive'
280 $asserter->setVarMapping(
282 Title
::newMainPage()->getCanonicalURL()
284 $asserter->setVarMapping(
286 $this->getServiceContainer()->getContentLanguage()->getHtmlCode()