use MediaWiki\Edit\PreparedEdit;
use MediaWiki\MediaWikiServices;
+use MediaWiki\Revision\SlotRecord;
use MediaWiki\Storage\RevisionSlotsUpdate;
+use PHPUnit\Framework\MockObject\MockObject;
use Wikimedia\TestingAccessWrapper;
/**
/**
* @param string|Title|WikiPage $page
- * @param string $text
+ * @param string|Content|Content[] $content
* @param int|null $model
*
* @return WikiPage
*/
- protected function createPage( $page, $text, $model = null, $user = null ) {
+ protected function createPage( $page, $content, $model = null, $user = null ) {
if ( is_string( $page ) || $page instanceof Title ) {
$page = $this->newPage( $page, $model );
}
- $content = ContentHandler::makeContent( $text, $page->getTitle(), $model );
- $page->doEditContent( $content, "testing", EDIT_NEW, false, $user );
+ if ( !$user ) {
+ $user = $this->getTestUser()->getUser();
+ }
+
+ if ( is_string( $content ) ) {
+ $content = ContentHandler::makeContent( $content, $page->getTitle(), $model );
+ }
+
+ if ( !is_array( $content ) ) {
+ $content = [ 'main' => $content ];
+ }
+
+ $updater = $page->newPageUpdater( $user );
+
+ foreach ( $content as $role => $cnt ) {
+ $updater->setContent( $role, $cnt );
+ }
+
+ $updater->saveRevision( CommentStoreComment::newUnsavedComment( "testing" ) );
+ if ( !$updater->wasSuccessful() ) {
+ $this->fail( $updater->getStatus()->getWikiText() );
+ }
return $page;
}
);
$logId = $status->getValue();
$actorQuery = ActorMigration::newMigration()->getJoin( 'log_user' );
+ $commentQuery = MediaWikiServices::getInstance()->getCommentStore()->getJoin( 'log_comment' );
$this->assertSelect(
- [ 'logging' ] + $actorQuery['tables'], /* table */
+ [ 'logging' ] + $actorQuery['tables'] + $commentQuery['tables'], /* table */
[
'log_type',
'log_action',
- 'log_comment',
+ 'log_comment' => $commentQuery['fields']['log_comment_text'],
'log_user' => $actorQuery['fields']['log_user'],
'log_user_text' => $actorQuery['fields']['log_user_text'],
'log_namespace',
$page->getTitle()->getDBkey(),
] ],
[],
- $actorQuery['joins']
+ $actorQuery['joins'] + $commentQuery['joins']
);
}
);
$logId = $status->getValue();
$actorQuery = ActorMigration::newMigration()->getJoin( 'log_user' );
+ $commentQuery = MediaWikiServices::getInstance()->getCommentStore()->getJoin( 'log_comment' );
$this->assertSelect(
- [ 'logging' ] + $actorQuery['tables'], /* table */
+ [ 'logging' ] + $actorQuery['tables'] + $commentQuery['tables'], /* table */
[
'log_type',
'log_action',
- 'log_comment',
+ 'log_comment' => $commentQuery['fields']['log_comment_text'],
'log_user' => $actorQuery['fields']['log_user'],
'log_user_text' => $actorQuery['fields']['log_user_text'],
'log_namespace',
$page->getTitle()->getDBkey(),
] ],
[],
- $actorQuery['joins']
+ $actorQuery['joins'] + $commentQuery['joins']
);
}
);
$logId = $status->getValue();
$actorQuery = ActorMigration::newMigration()->getJoin( 'log_user' );
+ $commentQuery = MediaWikiServices::getInstance()->getCommentStore()->getJoin( 'log_comment' );
$this->assertSelect(
- [ 'logging' ] + $actorQuery['tables'], /* table */
+ [ 'logging' ] + $actorQuery['tables'] + $commentQuery['tables'], /* table */
[
'log_type',
'log_action',
- 'log_comment',
+ 'log_comment' => $commentQuery['fields']['log_comment_text'],
'log_user' => $actorQuery['fields']['log_user'],
'log_user_text' => $actorQuery['fields']['log_user_text'],
'log_namespace',
$page->getTitle()->getDBkey(),
] ],
[],
- $actorQuery['joins']
+ $actorQuery['joins'] + $commentQuery['joins']
);
$this->assertNull(
* @covers WikiPage::doDeleteUpdates
*/
public function testDoDeleteUpdates() {
+ $user = $this->getTestUser()->getUser();
$page = $this->createPage(
__METHOD__,
"[[original text]] foo",
CONTENT_MODEL_WIKITEXT
);
$id = $page->getId();
+ $page->loadPageData(); // make sure the current revision is cached.
// Similar to MovePage logic
wfGetDB( DB_MASTER )->delete( 'page', [ 'page_id' => $id ], __METHOD__ );
- $page->doDeleteUpdates( $id );
+ $page->doDeleteUpdates( $page->getId(), $page->getContent(), $page->getRevision(), $user );
// Run the job queue
JobQueueGroup::destroySingletons();
$this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
}
+ /**
+ * @param string $name
+ *
+ * @return ContentHandler
+ */
+ protected function defineMockContentModelForUpdateTesting( $name ) {
+ /** @var ContentHandler|MockObject $handler */
+ $handler = $this->getMockBuilder( TextContentHandler::class )
+ ->setConstructorArgs( [ $name ] )
+ ->setMethods(
+ [ 'getSecondaryDataUpdates', 'getDeletionUpdates', 'unserializeContent' ]
+ )
+ ->getMock();
+
+ $dataUpdate = new MWCallableUpdate( 'time' );
+ $dataUpdate->_name = "$name data update";
+
+ $deletionUpdate = new MWCallableUpdate( 'time' );
+ $deletionUpdate->_name = "$name deletion update";
+
+ $handler->method( 'getSecondaryDataUpdates' )->willReturn( [ $dataUpdate ] );
+ $handler->method( 'getDeletionUpdates' )->willReturn( [ $deletionUpdate ] );
+ $handler->method( 'unserializeContent' )->willReturnCallback(
+ function ( $text ) use ( $handler ) {
+ return $this->createMockContent( $handler, $text );
+ }
+ );
+
+ $this->mergeMwGlobalArrayValue(
+ 'wgContentHandlers', [
+ $name => function () use ( $handler ){
+ return $handler;
+ }
+ ]
+ );
+
+ return $handler;
+ }
+
+ /**
+ * @param ContentHandler $handler
+ * @param string $text
+ *
+ * @return Content
+ */
+ protected function createMockContent( ContentHandler $handler, $text ) {
+ /** @var Content|MockObject $content */
+ $content = $this->getMockBuilder( TextContent::class )
+ ->setConstructorArgs( [ $text ] )
+ ->setMethods( [ 'getModel', 'getContentHandler' ] )
+ ->getMock();
+
+ $content->method( 'getModel' )->willReturn( $handler->getModelID() );
+ $content->method( 'getContentHandler' )->willReturn( $handler );
+
+ return $content;
+ }
+
+ public function testGetDeletionUpdates() {
+ $m1 = $this->defineMockContentModelForUpdateTesting( 'M1' );
+
+ $mainContent1 = $this->createMockContent( $m1, 'main 1' );
+
+ $page = new WikiPage( Title::newFromText( __METHOD__ ) );
+ $page = $this->createPage(
+ $page,
+ [ 'main' => $mainContent1 ]
+ );
+
+ $dataUpdates = $page->getDeletionUpdates( $page->getRevisionRecord() );
+ $this->assertNotEmpty( $dataUpdates );
+
+ $updateNames = array_map( function ( $du ) {
+ return isset( $du->_name ) ? $du->_name : get_class( $du );
+ }, $dataUpdates );
+
+ $this->assertContains( LinksDeletionUpdate::class, $updateNames );
+ $this->assertContains( 'M1 deletion update', $updateNames );
+ }
+
/**
* @covers WikiPage::getRevision
*/
"#REDIRECT [[hello world]]",
"Hello world"
],
+ // The below added to protect against Media namespace
+ // redirects which throw a fatal: (T203942)
+ [
+ 'WikiPageTest_testGetRedirectTarget_3',
+ CONTENT_MODEL_WIKITEXT,
+ "#REDIRECT [[Media:hello_world]]",
+ "File:Hello world"
+ ],
+ // Test fragments longer than 255 bytes (T207876)
+ [
+ 'WikiPageTest_testGetRedirectTarget_4',
+ CONTENT_MODEL_WIKITEXT,
+ // phpcs:ignore Generic.Files.LineLength
+ '#REDIRECT [[Foobar#🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴]]',
+ // phpcs:ignore Generic.Files.LineLength
+ 'Foobar#🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴🏴...'
+ ]
];
}
# now, test the actual redirect
$t = $page->getRedirectTarget();
- $this->assertEquals( $target, is_null( $t ) ? null : $t->getPrefixedText() );
+ $this->assertEquals( $target, is_null( $t ) ? null : $t->getFullText() );
}
/**
);
// TODO: MCR: assert origin once we write slot data
- // $mainSlot = $page->getRevision()->getRevisionRecord()->getSlot( 'main' );
+ // $mainSlot = $page->getRevision()->getRevisionRecord()->getSlot( SlotRecord::MAIN );
// $this->assertTrue( $mainSlot->isInherited(), 'isInherited' );
// $this->assertSame( $rev2->getId(), $mainSlot->getOrigin(), 'getOrigin' );
}
wfTimestamp( TS_UNIX, $initialRevision->getTimestamp() ) - 1
);
- $olderRevison = new Revision(
+ $olderRevision = new Revision(
[
'id' => 9989,
'page' => $page->getId(),
]
);
- $result = $page->updateIfNewerOn( $this->db, $olderRevison );
+ $result = $page->updateIfNewerOn( $this->db, $olderRevision );
$this->assertFalse( $result );
}
// Make sure the log entry looks good
// log_params is not checked here
$actorQuery = ActorMigration::newMigration()->getJoin( 'log_user' );
+ $commentQuery = MediaWikiServices::getInstance()->getCommentStore()->getJoin( 'log_comment' );
$this->assertSelect(
- [ 'logging' ] + $actorQuery['tables'],
+ [ 'logging' ] + $actorQuery['tables'] + $commentQuery['tables'],
[
- 'log_comment',
+ 'log_comment' => $commentQuery['fields']['log_comment_text'],
'log_user' => $actorQuery['fields']['log_user'],
'log_user_text' => $actorQuery['fields']['log_user_text'],
'log_namespace',
$page->getTitle()->getDBkey(),
] ],
[],
- $actorQuery['joins']
+ $actorQuery['joins'] + $commentQuery['joins']
);
}
// provide context, so the cache can be kept in place
$slotsUpdate = new revisionSlotsUpdate();
- $slotsUpdate->modifyContent( 'main', $content );
+ $slotsUpdate->modifyContent( SlotRecord::MAIN, $content );
$updater = $page->newPageUpdater( $user, $slotsUpdate );
- $updater->setContent( 'main', $content );
+ $updater->setContent( SlotRecord::MAIN, $content );
$revision = $updater->saveRevision(
CommentStoreComment::newUnsavedComment( 'test' ),
EDIT_NEW
$user = $revision->getUser();
$slotsUpdate = new RevisionSlotsUpdate();
- $slotsUpdate->modifyContent( 'main', new WikitextContent( 'Hello World' ) );
+ $slotsUpdate->modifyContent( SlotRecord::MAIN, new WikitextContent( 'Hello World' ) );
// get a virgin updater
$updater1 = $page->getDerivedDataUpdater( $user );
$this->assertSame( $updater1, $page->getDerivedDataUpdater( $user, $revision ) );
$slotsUpdate = RevisionSlotsUpdate::newFromContent(
- [ 'main' => $revision->getContent( 'main' ) ]
+ [ SlotRecord::MAIN => $revision->getContent( SlotRecord::MAIN ) ]
);
$this->assertSame( $updater1, $page->getDerivedDataUpdater( $user, null, $slotsUpdate ) );