'https://example.com/rights', MainConfigNames::RightsText => 'some rights', ] ), $this->getServiceContainer()->getRevisionLookup(), $this->getServiceContainer()->getTitleFormatter(), $this->getServiceContainer()->getPageStore(), $this->getServiceContainer()->getTitleFactory(), $this->getServiceContainer()->getConnectionProvider(), $this->getServiceContainer()->getChangeTagsStore() ); $authority = $authority ?: $this->mockRegisteredUltimateAuthority(); $helper->init( $authority, $params ); return $helper; } public function testGetRole() { $helper = $this->newHelper(); $this->assertSame( SlotRecord::MAIN, $helper->getRole() ); } public function testGetTitle() { $this->getExistingTestPage( 'Foo' ); $helper = $this->newHelper( [ 'title' => 'Foo' ] ); $this->assertSame( 'Foo', $helper->getTitleText() ); $this->assertInstanceOf( ExistingPageRecord::class, $helper->getPage() ); $this->assertSame( 'Foo', $this->getServiceContainer()->getTitleFormatter()->getPrefixedDBkey( $helper->getPage() ) ); } public function testGetTargetRevisionAndContent() { $page = $this->getExistingTestPage( __METHOD__ ); $rev = $page->getRevisionRecord(); $helper = $this->newHelper( [ 'title' => $page->getTitle()->getPrefixedDBkey() ] ); $targetRev = $helper->getTargetRevision(); $this->assertInstanceOf( RevisionRecord::class, $targetRev ); $this->assertSame( $rev->getId(), $targetRev->getId() ); $pageContent = $helper->getContent(); $this->assertSame( $rev->getContent( SlotRecord::MAIN )->serialize(), $pageContent->serialize() ); } /** * Ensure we can load the page with title "0" (T353687). */ public function testT353687() { $page = $this->getExistingTestPage( '0' ); $rev = $page->getRevisionRecord(); $helper = $this->newHelper( [ 'title' => $page->getTitle()->getPrefixedDBkey() ] ); // Key assertion: this should not throw! $helper->checkAccess(); $targetRev = $helper->getTargetRevision(); $this->assertInstanceOf( RevisionRecord::class, $targetRev ); $this->assertSame( $rev->getId(), $targetRev->getId() ); } public function testNoTitle() { $helper = $this->newHelper(); $this->assertNull( $helper->getTitleText() ); $this->assertNull( $helper->getPage() ); $this->assertFalse( $helper->hasContent() ); $this->assertNull( $helper->getTargetRevision() ); try { $helper->getContent(); $this->fail( 'Expected HttpException' ); } catch ( HttpException $ex ) { $this->assertSame( 404, $ex->getCode() ); } try { $helper->checkAccess(); $this->fail( 'Expected HttpException' ); } catch ( HttpException $ex ) { $this->assertSame( 404, $ex->getCode() ); } } public static function provideBadTitle() { yield [ '_' ]; yield [ '::Hello' ]; yield [ 'Special:Blankpage' ]; } /** * @dataProvider provideBadTitle */ public function testBadTitle( $badTitle ) { $helper = $this->newHelper( [ 'title' => $badTitle ] ); $this->assertNotNull( $helper->getTitleText() ); $this->assertNull( $helper->getPage() ); $this->assertFalse( $helper->hasContent() ); $this->assertNull( $helper->getTargetRevision() ); try { $helper->getContent(); $this->fail( 'Expected HttpException' ); } catch ( HttpException $ex ) { $this->assertSame( 404, $ex->getCode() ); } try { $helper->checkAccess(); $this->fail( 'Expected HttpException' ); } catch ( HttpException $ex ) { $this->assertSame( 404, $ex->getCode() ); } } public function testCheckHasContent() { $page = $this->getNonexistingTestPage( __METHOD__ )->getDBkey(); $helper = $this->newHelper( [ 'title' => $page ] ); $this->expectException( LocalizedHttpException::class ); $this->expectExceptionCode( 404 ); $helper->checkHasContent(); } public function testCheckAccessPermission() { $helper = $this->newHelper(); $this->expectException( LocalizedHttpException::class ); $this->expectExceptionCode( 403 ); $helper->checkAccessPermission(); } public function testNonExistingPage() { $page = $this->getNonexistingTestPage( __METHOD__ ); $title = $page->getTitle(); $helper = $this->newHelper( [ 'title' => $title->getPrefixedDBkey() ] ); $this->assertSame( $title->getPrefixedDBkey(), $helper->getTitleText() ); $this->assertNull( $helper->getPage() ); $this->assertFalse( $helper->hasContent() ); $this->assertTrue( $helper->isAccessible() ); $this->assertNull( $helper->getTargetRevision() ); $this->assertNull( $helper->getLastModified() ); $this->assertSame( self::NO_REVISION_ETAG, $helper->getETag() ); try { $helper->getContent(); $this->fail( 'Expected HttpException' ); } catch ( HttpException $ex ) { $this->assertSame( 404, $ex->getCode() ); } try { $helper->checkAccess(); $this->fail( 'Expected HttpException' ); } catch ( HttpException $ex ) { $this->assertSame( 404, $ex->getCode() ); } } public function testForbidenPage() { $page = $this->getExistingTestPage( __METHOD__ ); $title = $page->getTitle(); $helper = $this->newHelper( [ 'title' => $title->getPrefixedDBkey() ], $this->mockAnonNullAuthority() ); $this->assertSame( $title->getPrefixedDBkey(), $helper->getTitleText() ); $this->assertTrue( $helper->getPage()->isSamePageAs( $title ) ); $this->assertTrue( $helper->hasContent() ); $this->assertFalse( $helper->useDefaultSystemMessage() ); $this->assertNull( $helper->getDefaultSystemMessage() ); $this->assertFalse( $helper->isAccessible() ); $this->assertNull( $helper->getLastModified() ); try { $helper->checkAccess(); $this->fail( 'Expected HttpException' ); } catch ( HttpException $ex ) { $this->assertSame( 403, $ex->getCode() ); } } public function testForbiddenMessagePage() { $page = $this->getNonexistingTestPage( Title::makeTitle( NS_MEDIAWIKI, 'Logouttext' ) ); $title = $page->getTitle(); $helper = $this->newHelper( [ 'title' => $title->getPrefixedDBkey() ], $this->mockAnonNullAuthority() ); $this->assertSame( $title->getPrefixedDBkey(), $helper->getTitleText() ); $this->assertNull( $helper->getPage() ); $this->assertTrue( $helper->hasContent() ); $this->assertTrue( $helper->useDefaultSystemMessage() ); $this->assertNotNull( $helper->getDefaultSystemMessage() ); $this->assertFalse( $helper->isAccessible() ); $this->assertNull( $helper->getLastModified() ); $this->expectException( HttpException::class ); $this->expectExceptionCode( 403 ); $helper->checkAccess(); } public function testMessagePage() { $page = $this->getNonexistingTestPage( Title::makeTitle( NS_MEDIAWIKI, 'Logouttext' ) ); $title = $page->getTitle(); $helper = $this->newHelper( [ 'title' => $title->getPrefixedDBkey() ], $this->mockAnonUltimateAuthority() ); $this->assertSame( $title->getPrefixedDBkey(), $helper->getTitleText() ); $this->assertNull( $helper->getPage() ); $this->assertTrue( $helper->hasContent() ); $this->assertTrue( $helper->useDefaultSystemMessage() ); $this->assertNotNull( $helper->getDefaultSystemMessage() ); $this->assertTrue( $helper->isAccessible() ); $this->assertNull( $helper->getLastModified() ); // The line below should not throw any exception $helper->checkAccess(); } public static function provideRedirectsAllowed() { yield [ [], true ]; yield [ [ 'redirect' => true ], true ]; yield [ [ 'redirect' => false ], false ]; } /** * @dataProvider provideRedirectsAllowed */ public function testRedirectsAllowed( array $params, bool $allowRedirect ) { $page = $this->getNonexistingTestPage( Title::makeTitle( NS_MEDIAWIKI, 'Logouttext' ) ); $title = $page->getTitle(); $helper = $this->newHelper( $params + [ 'title' => $title->getPrefixedDBkey() ], $this->mockAnonUltimateAuthority() ); $this->assertSame( $allowRedirect, $helper->getRedirectsAllowed() ); } public function testParameterSettings() { $helper = $this->newHelper(); $settings = $helper->getParamSettings(); $this->assertArrayHasKey( 'title', $settings ); } public function testCacheControl() { $helper = $this->newHelper(); $response = new Response(); $helper->setCacheControl( $response ); // default $this->assertStringContainsString( 'max-age=5', $response->getHeaderLine( 'Cache-Control' ) ); $helper->setCacheControl( $response, 2 ); // explicit $this->assertStringContainsString( 'max-age=2', $response->getHeaderLine( 'Cache-Control' ) ); $helper->setCacheControl( $response, 1000 * 1000 ); // too big $this->assertStringContainsString( 'max-age=5', $response->getHeaderLine( 'Cache-Control' ) ); } public function testConstructMetadata() { $page = $this->getExistingTestPage( __METHOD__ ); $title = $page->getTitle(); $revision = $page->getRevisionRecord(); $content = $revision->getContent( SlotRecord::MAIN ); $expected = [ 'id' => $title->getArticleID(), 'key' => $title->getPrefixedDBkey(), 'title' => $title->getPrefixedText(), 'latest' => [ 'id' => $revision->getId(), 'timestamp' => wfTimestampOrNull( TS_ISO_8601, $revision->getTimestamp() ) ], 'content_model' => $content->getModel(), 'license' => [ 'url' => 'https://example.com/rights', 'title' => 'some rights', ] ]; $helper = $this->newHelper( [ 'title' => $title->getPrefixedDBkey() ] ); $data = $helper->constructMetadata(); $this->assertEquals( $expected, $data ); } public function provideConstructRestbaseCompatibleMetadata() { $pageName = 'User:Morg'; $page = PageIdentityValue::localIdentity( 7, NS_USER, 'Morg' ); $user = UserIdentityValue::newRegistered( 444, 'Morg' ); $comment = CommentStoreComment::newUnsavedComment( 'just an edit' ); $timestamp = '20220102112233'; $rev = new MutableRevisionRecord( $page ); $rev->setId( 123 ); $rev->setUser( $user ); $rev->setComment( $comment ); $rev->setTimestamp( $timestamp ); $expected = [ 'title' => $pageName, 'page_id' => 7, 'rev' => 123, 'tid' => 'DUMMY', 'namespace' => NS_USER, 'user_id' => 444, 'user_text' => 'Morg', 'comment' => $comment->text, 'timestamp' => wfTimestampOrNull( TS_ISO_8601, $timestamp ), 'tags' => [], 'restrictions' => [], 'page_language' => 'en', 'redirect' => false ]; yield [ $pageName, $rev, $expected ]; // Construct a revision with a hidden comment $rev = new MutableRevisionRecord( $page ); $rev->setId( 123 ); $rev->setUser( $user ); $rev->setComment( $comment ); $rev->setTimestamp( $timestamp ); $rev->setVisibility( RevisionRecord::DELETED_COMMENT ); $expectedHiddenComment = [ 'comment' => null, 'restrictions' => [ 'commenthidden' ], ] + $expected; yield [ $pageName, $rev, $expectedHiddenComment ]; // Construct a revision with a suppressed user $rev = new MutableRevisionRecord( $page ); $rev->setId( 123 ); $rev->setUser( $user ); $rev->setComment( $comment ); $rev->setTimestamp( $timestamp ); $rev->setVisibility( RevisionRecord::DELETED_USER ); $expectedHiddenComment = [ 'user_text' => null, 'restrictions' => [ 'userhidden' ], ] + $expected; yield [ $pageName, $rev, $expectedHiddenComment ]; } /** * @dataProvider provideConstructRestbaseCompatibleMetadata */ public function testConstructRestbaseCompatibleMetadata( string $pageName, RevisionRecord $revision, array $expected ) { $helper = $this->newHelper( [ 'title' => $pageName ] ); $helperAccess = TestingAccessWrapper::newFromObject( $helper ); $helperAccess->pageIdentity = $revision->getPage(); $helperAccess->targetRevision = $revision; $data = $helper->constructRestbaseCompatibleMetadata(); $this->assertEquals( $expected, $data ); } }