2 namespace MediaWiki\Tests\Page
;
5 use InvalidArgumentException
;
6 use LinkCacheTestTrait
;
7 use MediaWiki\Config\ServiceOptions
;
8 use MediaWiki\DAO\WikiAwareEntity
;
9 use MediaWiki\MainConfigNames
;
10 use MediaWiki\Page\PageIdentity
;
11 use MediaWiki\Page\PageIdentityValue
;
12 use MediaWiki\Page\PageRecord
;
13 use MediaWiki\Page\PageStore
;
14 use MediaWiki\Title\Title
;
15 use MediaWiki\Title\TitleValue
;
16 use MediaWikiIntegrationTestCase
;
18 use Wikimedia\Assert\PreconditionException
;
19 use Wikimedia\Rdbms\IDatabase
;
20 use Wikimedia\Rdbms\IDBAccessObject
;
21 use Wikimedia\Rdbms\LoadBalancer
;
22 use Wikimedia\Stats\Metrics\MetricInterface
;
23 use Wikimedia\Stats\StatsFactory
;
28 class PageStoreTest
extends MediaWikiIntegrationTestCase
{
31 use LinkCacheTestTrait
;
33 private StatsFactory
$statsFactory;
34 private MetricInterface
$linkCacheAccesses;
36 protected function setUp(): void
{
38 $this->statsFactory
= StatsFactory
::newNull();
40 $this->linkCacheAccesses
= $this->statsFactory
->getCounter( 'pagestore_linkcache_accesses_total' );
44 * @param array $options
45 * @param array $params
50 private function getPageStore( $options = [], $params = [] ) {
51 $services = $this->getServiceContainer();
53 $serviceOptions = new ServiceOptions(
54 PageStore
::CONSTRUCTOR_OPTIONS
,
56 MainConfigNames
::LanguageCode
=> $services->getContentLanguageCode()->toString(),
57 MainConfigNames
::PageLanguageUseDB
=> true,
63 $params['dbLoadBalancer'] ??
$services->getDBLoadBalancer(),
64 $services->getNamespaceInfo(),
65 $services->getTitleParser(),
66 array_key_exists( 'linkCache', $params )
67 ?
$params['linkCache']
68 : $services->getLinkCache(),
70 $params['wikiId'] ?? WikiAwareEntity
::LOCAL
74 private function assertSamePage( PageIdentity
$expected, PageIdentity
$actual ) {
75 // NOTE: Leave it to the caller to compare the wiki IDs. $expected may be local
76 // even if $actual belongs to a (pretend) sister site.
77 $expWiki = $expected->getWikiId();
78 $actWiki = $actual->getWikiId();
80 $this->assertSame( $expected->getId( $expWiki ), $actual->getId( $actWiki ) );
81 $this->assertSame( $expected->getNamespace(), $actual->getNamespace() );
82 $this->assertSame( $expected->getDBkey(), $actual->getDBkey() );
84 if ( $expected instanceof PageRecord
) {
85 $this->assertInstanceOf( PageRecord
::class, $actual );
87 /** @var PageRecord $actual */
88 $this->assertSame( $expected->getLatest( $expWiki ), $actual->getLatest( $actWiki ) );
89 $this->assertSame( $expected->getLanguage(), $actual->getLanguage() );
90 $this->assertSame( $expected->getTouched(), $actual->getTouched() );
95 * Test that we get a PageIdentity for a link referencing a non-existing page
96 * @covers \MediaWiki\Page\PageStore::getPageForLink
98 public function testGetPageForLink_nonexisting() {
99 $nonexistingPage = $this->getNonexistingTestPage();
100 $pageStore = $this->getPageStore();
102 $page = $pageStore->getPageForLink( $nonexistingPage->getTitle() );
104 $this->assertTrue( $page->canExist() );
105 $this->assertFalse( $page->exists() );
107 $this->assertSamePage( $nonexistingPage->getTitle(), $page );
111 * Test that we get a PageRecord for a link to an existing page.
112 * @covers \MediaWiki\Page\PageStore::getPageForLink
114 public function testGetPageForLink_existing() {
115 $existingPage = $this->getExistingTestPage();
116 $pageStore = $this->getPageStore();
118 $page = $pageStore->getPageForLink( $existingPage->getTitle() );
120 $this->assertTrue( $page->exists() );
121 $this->assertInstanceOf( PageRecord
::class, $page );
122 $this->assertSamePage( $existingPage->toPageRecord(), $page );
126 * Test that getPageForLink() can get a PageIdentity from another wiki
127 * @covers \MediaWiki\Page\PageStore::getPageForLink
129 public function testGetPageForLink_crossWiki() {
130 $wikiId = $this->getDb()->getDomainID(); // pretend sister site
132 $nonexistingPage = $this->getNonexistingTestPage();
133 $pageStore = $this->getPageStore( [], [ 'wikiId' => $wikiId, 'linkCache' => null ] );
135 $page = $pageStore->getPageForLink( $nonexistingPage->getTitle() );
137 $this->assertSame( $wikiId, $page->getWikiId() );
138 $this->assertSamePage( $nonexistingPage->getTitle(), $page );
142 * Test that getPageForLink() maps NS_MEDIA to NS_FILE
143 * @covers \MediaWiki\Page\PageStore::getPageForLink
145 public function testGetPageForLink_media() {
146 $link = new TitleValue( NS_MEDIA
, 'Test913847659234.jpg' );
147 $pageStore = $this->getPageStore();
149 $page = $pageStore->getPageForLink( $link );
151 $this->assertTrue( $page->canExist() );
152 $this->assertSame( NS_FILE
, $page->getNamespace() );
153 $this->assertSame( $link->getDBkey(), $page->getDBkey() );
156 public static function provideInvalidLinks() {
157 yield
'section link' => [ new TitleValue( NS_MAIN
, '', '#References' ) ];
158 yield
'special page' => [ new TitleValue( NS_SPECIAL
, 'Test' ) ];
159 yield
'interwiki link' => [ new TitleValue( NS_MAIN
, 'Test', '', 'acme' ) ];
163 * Test that getPageForLink() throws InvalidArgumentException when presented with
164 * a link that does not refer to a proper page.
166 * @dataProvider provideInvalidLinks
167 * @covers \MediaWiki\Page\PageStore::getPageForLink
169 public function testGetPageForLink_invalid( $link ) {
170 $pageStore = $this->getPageStore();
172 $this->expectException( InvalidArgumentException
::class );
173 $pageStore->getPageForLink( $link );
177 * Test that we get a PageRecord for an existing page by name
178 * @covers \MediaWiki\Page\PageStore::getPageByName
180 public function testGetPageByName_existing() {
181 $existingPage = $this->getExistingTestPage();
182 $ns = $existingPage->getNamespace();
183 $dbkey = $existingPage->getDBkey();
185 $pageStore = $this->getPageStore();
186 $page = $pageStore->getPageByName( $ns, $dbkey );
188 $this->assertTrue( $page->exists() );
189 $this->assertSamePage( $existingPage, $page );
191 $linkCache = $this->getServiceContainer()->getLinkCache();
192 $this->assertSame( $page->getId(), $linkCache->getGoodLinkID( $page ) );
196 * Test that we get a PageRecord for an existing page by name
197 * with no LinkCache provided.
198 * @covers \MediaWiki\Page\PageStore::getPageByName
200 public function testGetPageByName_existing_noLinkCache() {
201 $existingPage = $this->getExistingTestPage();
202 $ns = $existingPage->getNamespace();
203 $dbkey = $existingPage->getDBkey();
205 $pageStore = $this->getPageStore( [], [ 'linkCache' => null ] );
206 $page = $pageStore->getPageByName( $ns, $dbkey );
208 $this->assertTrue( $page->exists() );
209 $this->assertSamePage( $existingPage, $page );
211 $linkCache = $this->getServiceContainer()->getLinkCache();
212 $this->assertSame( $page->getId(), $linkCache->getGoodLinkID( $page ) );
213 $this->assertSame( 0, $this->linkCacheAccesses
->getSampleCount() );
217 * Test that we get null if we look up a non-existing page by name
218 * @covers \MediaWiki\Page\PageStore::getPageByName
220 public function testGetPageByName_nonexisting() {
221 $nonexistingPage = $this->getNonexistingTestPage();
222 $ns = $nonexistingPage->getNamespace();
223 $dbkey = $nonexistingPage->getDBkey();
225 $pageStore = $this->getPageStore();
226 $page = $pageStore->getPageByName( $ns, $dbkey );
228 $this->assertNull( $page );
230 $linkCache = $this->getServiceContainer()->getLinkCache();
231 $this->assertTrue( $linkCache->isBadLink( $nonexistingPage ) );
235 * Test that we get null if we look up a page known to be not existing,
236 * without hitting the database.
237 * @covers \MediaWiki\Page\PageStore::getPageByName
239 public function testGetPageByName_nonexisting_cached() {
240 $nonexistingPage = $this->getNonexistingTestPage();
241 $ns = $nonexistingPage->getNamespace();
242 $dbkey = $nonexistingPage->getDBkey();
244 $linkCache = $this->getServiceContainer()->getLinkCache();
245 $linkCache->addBadLinkObj( $nonexistingPage );
247 $mockLB = $this->createNoOpMock( LoadBalancer
::class );
248 $pageStore = $this->getPageStore( [], [ 'doLoadBalancer' => $mockLB ] );
249 $page = $pageStore->getPageByName( $ns, $dbkey );
251 $this->assertNull( $page );
252 $this->assertTrue( $linkCache->isBadLink( $nonexistingPage ) );
253 $this->assertSame( 1, $this->linkCacheAccesses
->getSampleCount() );
257 * Test that we get a PageRecord from a cached row
258 * @covers \MediaWiki\Page\PageStore::getPageByName
260 public function testGetPageByName_cachedFullRow() {
261 $nonexistingPage = $this->getNonexistingTestPage();
262 $ns = $nonexistingPage->getNamespace();
263 $dbkey = $nonexistingPage->getDBkey();
267 'page_namespace' => $ns,
268 'page_title' => $dbkey,
269 'page_is_redirect' => 0,
271 'page_touched' => '12345',
272 'page_links_updated' => '12345',
273 'page_latest' => 118,
275 'page_content_model' => CONTENT_FORMAT_TEXT
,
276 'page_lang' => 'xyz',
279 $linkCache = $this->getServiceContainer()->getLinkCache();
280 $linkCache->addGoodLinkObjFromRow( $nonexistingPage, $row );
282 $mockLB = $this->createNoOpMock( LoadBalancer
::class );
284 $pageStore = $this->getPageStore( [], [ 'doLoadBalancer' => $mockLB ] );
285 $page = $pageStore->getPageByName( $ns, $dbkey );
287 $this->assertSame( $row->page_id
, $page->getId() );
288 $this->assertSame( $row->page_namespace
, $page->getNamespace() );
289 $this->assertSame( $row->page_title
, $page->getDBkey() );
290 $this->assertSame( $row->page_latest
, $page->getLatest() );
291 $this->assertSame( 1, $this->linkCacheAccesses
->getSampleCount() );
295 * Test that we get a PageRecord when an incomplete row exists in the cache
296 * @covers \MediaWiki\Page\PageStore::getPageByName
298 public function testGetPageByName_cachedFakeRow() {
299 $nonexistingPage = $this->getNonexistingTestPage();
300 $ns = $nonexistingPage->getNamespace();
301 $dbkey = $nonexistingPage->getDBkey();
303 $linkCache = $this->getServiceContainer()->getLinkCache();
304 $linkCache->clearLink( $nonexistingPage );
306 // Has all fields needed by LinkCache, but not all fields needed by PageStore.
307 // This may happen when legacy code injects rows directly into LinkCache.
308 $this->addGoodLinkObject( 8, $nonexistingPage );
310 $pageStore = $this->getPageStore();
311 $page = $pageStore->getPageByName( $ns, $dbkey );
313 $this->assertSame( 8, $page->getId() );
314 $this->assertSame( $nonexistingPage->getNamespace(), $page->getNamespace() );
315 $this->assertSame( $nonexistingPage->getDBkey(), $page->getDBkey() );
316 $this->assertSame( 1, $this->linkCacheAccesses
->getSampleCount() );
320 * @covers \MediaWiki\Page\PageStore::getPageByText
322 public function testGetPageByText_existing() {
323 $existingPage = $this->getExistingTestPage();
325 $pageStore = $this->getPageStore();
326 $page = $pageStore->getPageByText( $existingPage->getTitle()->getPrefixedText() );
328 $this->assertTrue( $page->exists() );
329 $this->assertSamePage( $existingPage, $page );
331 $page = $pageStore->getExistingPageByText( $existingPage->getTitle()->getPrefixedText() );
333 $this->assertTrue( $page->exists() );
334 $this->assertSamePage( $existingPage, $page );
338 * @covers \MediaWiki\Page\PageStore::getPageByText
340 public function testGetPageByText_nonexisting() {
341 $nonexistingPage = $this->getNonexistingTestPage();
342 $pageStore = $this->getPageStore();
343 $page = $pageStore->getPageByText( $nonexistingPage->getTitle()->getPrefixedText() );
344 $this->assertFalse( $page->exists() );
345 $this->assertTrue( $nonexistingPage->isSamePageAs( $page ) );
349 * @covers \MediaWiki\Page\PageStore::getExistingPageByText
351 public function testGetExistingPageByText_existing() {
352 $existingPage = $this->getExistingTestPage();
354 $pageStore = $this->getPageStore();
355 $page = $pageStore->getExistingPageByText( $existingPage->getTitle()->getPrefixedText() );
357 $this->assertTrue( $page->exists() );
358 $this->assertSamePage( $existingPage, $page );
362 * @covers \MediaWiki\Page\PageStore::getExistingPageByText
364 public function testGetExistingPageByText_nonexisting() {
365 $nonexistingPage = $this->getNonexistingTestPage();
366 $pageStore = $this->getPageStore();
367 $page = $pageStore->getExistingPageByText( $nonexistingPage->getTitle()->getPrefixedText() );
368 $this->assertNull( $page );
372 * Configure the load balancer to route queries for the "foreign" domain to the test DB.
374 * @param string $wikiId
376 private function setDomainAlias( $wikiId ) {
377 $dbLoadBalancer = $this->getServiceContainer()->getDBLoadBalancer();
378 $dbLoadBalancer->setDomainAliases( [ $wikiId => $dbLoadBalancer->getLocalDomainID() ] );
382 * Test that we get a PageRecord from another wiki by name
383 * @covers \MediaWiki\Page\PageStore::getPageByName
385 public function testGetPageByName_crossWiki() {
387 $this->setDomainAlias( $wikiId );
389 $existingPage = $this->getExistingTestPage();
390 $ns = $existingPage->getNamespace();
391 $dbkey = $existingPage->getDBkey();
393 $pageStore = $this->getPageStore( [], [ 'wikiId' => $wikiId, 'linkCache' => null ] );
394 $page = $pageStore->getPageByName( $ns, $dbkey );
396 $this->assertSame( $wikiId, $page->getWikiId() );
397 $this->assertSamePage( $existingPage, $page );
400 public static function provideGetPageByName_invalid() {
401 yield
'empty title' => [ NS_MAIN
, '' ];
402 yield
'spaces in title' => [ NS_MAIN
, 'Foo Bar' ];
403 yield
'special page' => [ NS_SPECIAL
, 'Test' ];
404 yield
'media link' => [ NS_MEDIA
, 'Test' ];
408 * Test that getPageByName() throws InvalidArgumentException when presented with
409 * a link that does not refer to a proper page.
411 * @dataProvider provideGetPageByName_invalid
412 * @covers \MediaWiki\Page\PageStore::getPageByName
414 public function testGetPageByName_invalid( $ns, $dbkey ) {
415 $pageStore = $this->getPageStore();
417 $this->expectException( InvalidArgumentException
::class );
418 $pageStore->getPageByName( $ns, $dbkey );
421 public static function provideInvalidTitleText() {
422 yield
'empty' => [ '' ];
423 yield
'section' => [ '#foo' ];
424 yield
'autoblock' => [ 'User:#12345' ];
425 yield
'special' => [ 'Special:RecentChanges' ];
426 yield
'invalid' => [ 'foo|bar' ];
430 * @dataProvider provideInvalidTitleText
431 * @covers \MediaWiki\Page\PageStore::getPageByText
433 public function testGetPageByText_invalid( $text ) {
434 $pageStore = $this->getPageStore();
435 $page = $pageStore->getPageByText( $text );
436 $this->assertNull( $page );
440 * @dataProvider provideInvalidTitleText
441 * @covers \MediaWiki\Page\PageStore::getExistingPageByText
443 public function testGetExistingPageByText_invalid( $text ) {
444 $pageStore = $this->getPageStore();
445 $page = $pageStore->getExistingPageByText( $text );
446 $this->assertNull( $page );
450 * Test that we get a PageRecord for an existing page by id
451 * @covers \MediaWiki\Page\PageStore::getPageById
453 public function testGetPageById_existing() {
454 $existingPage = $this->getExistingTestPage();
456 $pageStore = $this->getPageStore();
457 $page = $pageStore->getPageById( $existingPage->getId() );
459 $this->assertTrue( $page->exists() );
460 $this->assertSamePage( $existingPage, $page );
464 * Test that we get null if we look up a non-existing page by id
465 * @covers \MediaWiki\Page\PageStore::getPageById
467 public function testGetPageById_nonexisting() {
468 $pageStore = $this->getPageStore();
469 $page = $pageStore->getPageById( 813451092 );
471 $this->assertNull( $page );
475 * Test that we get a PageRecord from another wiki by id
476 * @covers \MediaWiki\Page\PageStore::getPageById
478 public function testGetPageById_crossWiki() {
480 $this->setDomainAlias( $wikiId );
482 $existingPage = $this->getExistingTestPage();
484 $pageStore = $this->getPageStore( [], [ 'wikiId' => $wikiId, 'linkCache' => null ] );
485 $page = $pageStore->getPageById( $existingPage->getId() );
487 $this->assertSame( $wikiId, $page->getWikiId() );
488 $this->assertSamePage( $existingPage, $page );
492 * Test that we can correctly emulate the page_lang field.
493 * @covers \MediaWiki\Page\PageStore::getPageById
495 public function testGetPageById_noLanguage() {
496 $existingPage = $this->getExistingTestPage();
498 $pageStore = $this->getPageStore();
499 $page = $pageStore->getPageById( $existingPage->getId() );
501 $this->assertNull( $page->getLanguage() );
504 public static function provideGetPageById_invalid() {
505 yield
'zero' => [ 0 ];
506 yield
'negative' => [ -1 ];
510 * Test that getPageById() throws InvalidArgumentException for bad IDs.
512 * @dataProvider provideGetPageById_invalid
513 * @covers \MediaWiki\Page\PageStore::getPageById
515 public function testGetPageById_invalid( $id ) {
516 $pageStore = $this->getPageStore();
518 $this->expectException( InvalidArgumentException
::class );
519 $pageStore->getPageById( $id );
523 * Test that we get a PageRecord for an existing page by id
525 * @covers \MediaWiki\Page\PageStore::getPageByReference
527 public function testGetPageByIdentity_existing() {
528 $existingPage = $this->getExistingTestPage();
529 $identity = $existingPage->getTitle()->toPageIdentity();
531 $pageStore = $this->getPageStore();
532 $page = $pageStore->getPageByReference( $identity );
534 $this->assertTrue( $page->exists() );
535 $this->assertSamePage( $existingPage, $page );
539 * Test that we get a PageRecord from cached data even if we pass in a
540 * PageIdentity that provides a page ID (T296063#7520023).
542 * @covers \MediaWiki\Page\PageStore::getPageByReference
544 public function testGetPageByIdentity_cached() {
545 $title = $this->makeMockTitle( __METHOD__
, [ 'id' => 23 ] );
546 $this->addGoodLinkObject( 23, $title );
548 $pageStore = $this->getPageStore();
549 $page = $pageStore->getPageByReference( $title );
551 $this->assertNotNull( $page );
552 $this->assertSame( 23, $page->getId() );
556 * Test that we get null if we look up a page with ID 0
558 * @covers \MediaWiki\Page\PageStore::getPageByReference
560 public function testGetPageByIdentity_knowNonexisting() {
561 $nonexistingPage = new PageIdentityValue( 0, NS_MAIN
, 'Test', PageIdentity
::LOCAL
);
563 $pageStore = $this->getPageStore();
564 $page = $pageStore->getPageByReference( $nonexistingPage );
566 $this->assertNull( $page );
570 * Test that we get null if we look up a page with an ID that does not exist
572 * @covers \MediaWiki\Page\PageStore::getPageByReference
574 public function testGetPageByIdentity_notFound() {
575 $nonexistingPage = new PageIdentityValue( 523478562, NS_MAIN
, 'Test', PageIdentity
::LOCAL
);
577 $pageStore = $this->getPageStore();
578 $page = $pageStore->getPageByReference( $nonexistingPage );
580 $this->assertNull( $page );
584 * Test that getPageByIdentity() returns any ExistingPageRecord unchanged
586 * @covers \MediaWiki\Page\PageStore::getPageByReference
588 public function testGetPageByIdentity_PageRecord() {
589 $existingPage = $this->getExistingTestPage();
590 $rec = $existingPage->toPageRecord();
592 $pageStore = $this->getPageStore();
593 $page = $pageStore->getPageByReference( $rec );
595 $this->assertSame( $rec, $page );
599 * Test that we get a PageRecord from another wiki by id
601 * @covers \MediaWiki\Page\PageStore::getPageByReference
603 public function testGetPageByIdentity_crossWiki() {
605 $this->setDomainAlias( $wikiId );
607 $existingPage = $this->getExistingTestPage();
609 $identity = new PageIdentityValue(
610 $existingPage->getId(),
611 $existingPage->getNamespace(),
612 $existingPage->getDBkey(),
616 $pageStore = $this->getPageStore( [], [ 'wikiId' => $wikiId, 'linkCache' => null ] );
617 $page = $pageStore->getPageByReference( $identity );
619 $this->assertSame( $wikiId, $page->getWikiId() );
620 $this->assertSamePage( $existingPage, $page );
623 public function provideGetPageByIdentity_invalid() {
625 $this->makeMockTitle( '', [ 'fragment' => 'See also' ] ),
626 InvalidArgumentException
::class
629 $this->makeMockTitle( 'Blankpage', [ 'namespace' => NS_SPECIAL
] ),
630 InvalidArgumentException
::class
632 yield
'interwiki' => [
633 $this->makeMockTitle( 'Foo', [ 'interwiki' => 'acme' ] ),
634 InvalidArgumentException
::class
637 $identity = new PageIdentityValue( 7, NS_MAIN
, 'Test', 'acme' );
638 yield
'cross-wiki' => [ $identity, PreconditionException
::class ];
642 * Test that getPageByIdentity() throws InvalidArgumentException for bad IDs.
644 * @dataProvider provideGetPageByIdentity_invalid
645 * @covers \MediaWiki\Page\PageStore::getPageByReference
647 public function testGetPageByIdentity_invalid( $identity, $exception ) {
648 $pageStore = $this->getPageStore();
650 $this->expectException( $exception );
651 $pageStore->getPageByReference( $identity );
655 * @covers \MediaWiki\Page\PageStore::newPageRecordFromRow
656 * @covers \MediaWiki\Page\PageStore::getSelectFields
658 public function testNewPageRecordFromRow() {
659 $existingPage = $this->getExistingTestPage();
660 $pageStore = $this->getPageStore();
662 $row = $this->getDb()->newSelectQueryBuilder()
663 ->select( $pageStore->getSelectFields() )
665 ->where( [ 'page_id' => $existingPage->getId() ] )
668 $rec = $pageStore->newPageRecordFromRow( $row );
669 $this->assertSamePage( $existingPage, $rec );
673 * @covers \MediaWiki\Page\PageStore::newSelectQueryBuilder
675 public function testNewSelectQueryBuilder() {
676 $existingPage = $this->getExistingTestPage();
679 $this->setDomainAlias( $wikiId );
681 $pageStore = $this->getPageStore( [], [ 'wikiId' => $wikiId, 'linkCache' => null ] );
683 $rec = $pageStore->newSelectQueryBuilder()
684 ->wherePageIds( $existingPage->getId() )
687 $this->assertSame( $wikiId, $rec->getWikiId() );
688 $this->assertSamePage( $existingPage, $rec );
692 * @covers \MediaWiki\Page\PageStore::newSelectQueryBuilder
694 public function testNewSelectQueryBuilder_passDatabase() {
695 $pageStore = $this->getPageStore();
697 // Test that the provided DB connection is used.
698 $db = $this->createMock( IDatabase
::class );
699 $db->expects( $this->atLeastOnce() )->method( 'selectRow' )->willReturn( false );
701 $pageStore->newSelectQueryBuilder( $db )
706 * @covers \MediaWiki\Page\PageStore::newSelectQueryBuilder
708 public function testNewSelectQueryBuilder_passFlags() {
709 // Test that the provided DB connection is used.
710 $db = $this->createMock( IDatabase
::class );
711 $db->expects( $this->atLeastOnce() )->method( 'selectRow' )->willReturn( false );
713 // Test that the load balancer is asked for a master connection
714 $lb = $this->createMock( LoadBalancer
::class );
715 $lb->expects( $this->atLeastOnce() )
716 ->method( 'getConnection' )
720 $pageStore = $this->getPageStore(
722 MainConfigNames
::LanguageCode
=> 'qxx',
723 MainConfigNames
::PageLanguageUseDB
=> true,
725 [ 'dbLoadBalancer' => $lb ]
728 $pageStore->newSelectQueryBuilder( IDBAccessObject
::READ_LATEST
)
733 * @covers \MediaWiki\Page\PageStore::getSubpages
735 public function testGetSubpages() {
736 $existingPage = $this->getExistingTestPage();
737 $title = $existingPage->getTitle();
739 $this->overrideConfigValue(
740 MainConfigNames
::NamespacesWithSubpages
,
741 [ $title->getNamespace() => true ]
744 $existingSubpageA = $this->getExistingTestPage( $title->getSubpage( 'A' ) );
745 $existingSubpageB = $this->getExistingTestPage( $title->getSubpage( 'B' ) );
747 $notQuiteSubpageTitle = $title->getPrefixedDBkey() . 'X'; // no slash!
748 $this->getExistingTestPage( $notQuiteSubpageTitle );
750 $pageStore = $this->getPageStore();
752 $subpages = iterator_to_array( $pageStore->getSubpages( $title, 100 ) );
754 $this->assertCount( 2, $subpages );
755 $this->assertTrue( $existingSubpageA->isSamePageAs( $subpages[0] ) );
756 $this->assertTrue( $existingSubpageB->isSamePageAs( $subpages[1] ) );
758 // make sure the limit works as well
759 $this->assertCount( 1, iterator_to_array( $pageStore->getSubpages( $title, 1 ) ) );
763 * @covers \MediaWiki\Page\PageStore::getSubpages
765 public function testGetSubpages_disabled() {
766 $this->overrideConfigValue( MainConfigNames
::NamespacesWithSubpages
, [] );
768 $existingPage = $this->getExistingTestPage();
769 $title = $existingPage->getTitle();
771 $this->getExistingTestPage( $title->getSubpage( 'A' ) );
772 $this->getExistingTestPage( $title->getSubpage( 'B' ) );
774 $pageStore = $this->getPageStore();
775 $this->assertCount( 0, $pageStore->getSubpages( $title, 100 ) );
779 * See T295931. If removing TitleExists hook, remove this test.
781 * @covers \MediaWiki\Page\PageStore::getPageByReference
783 public function testGetPageByReferenceTitleExistsHook() {
784 $this->setTemporaryHook( 'TitleExists', static function ( $title, &$exists ) {
788 $this->getPageStore()->getPageByReference(
789 Title
::newFromText( __METHOD__
)