Introduce includes/Storage/PageUpdaterFactory

Change-Id: I2a060bfa8ac098edf24fc4d51212eeb7ddf3942d
This commit is contained in:
daniel 2021-07-16 19:32:30 +02:00
parent 7466a4c958
commit 1829057944
9 changed files with 522 additions and 98 deletions

View file

@ -83,6 +83,7 @@ use MediaWiki\Storage\BlobStoreFactory;
use MediaWiki\Storage\NameTableStore;
use MediaWiki\Storage\NameTableStoreFactory;
use MediaWiki\Storage\PageEditStash;
use MediaWiki\Storage\PageUpdaterFactory;
use MediaWiki\Storage\RevertedTagUpdateManager;
use MediaWiki\Tidy\TidyDriverBase;
use MediaWiki\User\ActorNormalization;
@ -1224,6 +1225,14 @@ class MediaWikiServices extends ServiceContainer {
return $this->getService( 'PageStoreFactory' );
}
/**
* @since 1.37
* @return PageUpdaterFactory
*/
public function getPageUpdaterFactory() : PageUpdaterFactory {
return $this->getService( 'PageUpdaterFactory' );
}
/**
* @since 1.29
* @return Parser

View file

@ -117,6 +117,7 @@ use MediaWiki\Storage\EditResultCache;
use MediaWiki\Storage\NameTableStore;
use MediaWiki\Storage\NameTableStoreFactory;
use MediaWiki\Storage\PageEditStash;
use MediaWiki\Storage\PageUpdaterFactory;
use MediaWiki\Storage\RevertedTagUpdateManager;
use MediaWiki\Storage\SqlBlobStore;
use MediaWiki\Tidy\RemexDriver;
@ -1032,6 +1033,42 @@ return [
);
},
'PageUpdaterFactory' => static function (
MediaWikiServices $services
): PageUpdaterFactory {
$editResultCache = new EditResultCache(
$services->getMainObjectStash(),
$services->getDBLoadBalancer(),
new ServiceOptions(
EditResultCache::CONSTRUCTOR_OPTIONS,
$services->getMainConfig()
)
);
return new PageUpdaterFactory(
$services->getRevisionStore(),
$services->getRevisionRenderer(),
$services->getSlotRoleRegistry(),
$services->getParserCache(),
$services->getJobQueueGroup(),
$services->getMessageCache(),
$services->getContentLanguage(),
$services->getDBLoadBalancerFactory(),
$services->getContentHandlerFactory(),
$services->getHookContainer(),
$editResultCache,
$services->getUserNameUtils(),
LoggerFactory::getInstance( 'SavePage' ),
new ServiceOptions(
PageUpdaterFactory::CONSTRUCTOR_OPTIONS,
$services->getMainConfig()
),
$services->getUserEditTracker(),
$services->getUserGroupManager(),
ChangeTags::getSoftwareTags()
);
},
'Parser' => static function ( MediaWikiServices $services ) : Parser {
return $services->getParserFactory()->create();
},

View file

@ -37,7 +37,6 @@ use MediaWiki\Content\IContentHandlerFactory;
use MediaWiki\HookContainer\HookContainer;
use MediaWiki\HookContainer\HookRunner;
use MediaWiki\Linker\LinkTarget;
use MediaWiki\Permissions\Authority;
use MediaWiki\Revision\MutableRevisionRecord;
use MediaWiki\Revision\RevisionAccessException;
use MediaWiki\Revision\RevisionRecord;
@ -80,7 +79,7 @@ class PageUpdater {
/**
* Options that have to be present in the ServiceOptions object passed to the constructor.
*
* @note When adding options here, also add them to PageUpdaterFactory::CONSTRUCTOR_OPTIONS.
* @internal
*/
public const CONSTRUCTOR_OPTIONS = [
@ -89,9 +88,9 @@ class PageUpdater {
];
/**
* @var Authority
* @var UserIdentity
*/
private $performer;
private $author;
/**
* @var WikiPage
@ -196,7 +195,7 @@ class PageUpdater {
private $serviceOptions;
/**
* @param Authority $performer
* @param UserIdentity $author
* @param WikiPage $wikiPage
* @param DerivedPageDataUpdater $derivedDataUpdater
* @param ILoadBalancer $loadBalancer
@ -211,7 +210,7 @@ class PageUpdater {
* obtained from ChangeTags::getSoftwareTags()
*/
public function __construct(
Authority $performer,
UserIdentity $author,
WikiPage $wikiPage,
DerivedPageDataUpdater $derivedDataUpdater,
ILoadBalancer $loadBalancer,
@ -227,7 +226,7 @@ class PageUpdater {
$serviceOptions->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
$this->serviceOptions = $serviceOptions;
$this->performer = $performer;
$this->author = $author;
$this->wikiPage = $wikiPage;
$this->derivedDataUpdater = $derivedDataUpdater;
@ -775,11 +774,9 @@ class PageUpdater {
$useStashed = $this->ajaxEditStash;
}
$user = $this->performer->getUser();
// Prepare the update. This performs PST and generates the canonical ParserOutput.
$this->derivedDataUpdater->prepareContent(
$user,
$this->author,
$this->slotsUpdate,
$useStashed
);
@ -788,7 +785,7 @@ class PageUpdater {
$renderedRevision = $this->derivedDataUpdater->getRenderedRevision();
$hookStatus = Status::newGood( [] );
$allowedByHook = $this->hookRunner->onMultiContentSave(
$renderedRevision, $user, $summary, $flags, $hookStatus
$renderedRevision, $this->author, $summary, $flags, $hookStatus
);
if ( $allowedByHook && $this->hookContainer->isRegistered( 'PageContentSave' ) ) {
// Also run the legacy hook.
@ -796,7 +793,7 @@ class PageUpdater {
// and only if something uses the legacy hook.
$mainContent = $this->derivedDataUpdater->getSlots()->getContent( SlotRecord::MAIN );
$legacyUser = self::toLegacyUser( $user );
$legacyUser = self::toLegacyUser( $this->author );
// Deprecated since 1.35.
$allowedByHook = $this->hookRunner->onPageContentSave(
@ -826,16 +823,16 @@ class PageUpdater {
// Actually create the revision and create/update the page.
// Do NOT yet set $this->status!
if ( $flags & EDIT_UPDATE ) {
$status = $this->doModify( $summary, $user, $flags );
$status = $this->doModify( $summary, $this->author, $flags );
} else {
$status = $this->doCreate( $summary, $user, $flags );
$status = $this->doCreate( $summary, $this->author, $flags );
}
// Promote user to any groups they meet the criteria for
DeferredUpdates::addCallableUpdate( function () use ( $user ) {
$this->userGroupManager->addUserToAutopromoteOnceGroups( $user, 'onEdit' );
DeferredUpdates::addCallableUpdate( function () {
$this->userGroupManager->addUserToAutopromoteOnceGroups( $this->author, 'onEdit' );
// Also run 'onView' for backwards compatibility
$this->userGroupManager->addUserToAutopromoteOnceGroups( $user, 'onView' );
$this->userGroupManager->addUserToAutopromoteOnceGroups( $this->author, 'onView' );
} );
// NOTE: set $this->status only after all hooks have been called,
@ -920,7 +917,7 @@ class PageUpdater {
// do we need PST?
$this->status = $this->doUpdate( $this->performer->getUser(), $revision );
$this->status = $this->doUpdate( $this->author, $revision );
}
/**

View file

@ -0,0 +1,314 @@
<?php
/**
* A factory for DerivedPageDataUpdater instances.
*
* 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
*
* @file
*/
namespace MediaWiki\Storage;
use JobQueueGroup;
use Language;
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Content\IContentHandlerFactory;
use MediaWiki\HookContainer\HookContainer;
use MediaWiki\Revision\RevisionRenderer;
use MediaWiki\Revision\RevisionStore;
use MediaWiki\Revision\SlotRoleRegistry;
use MediaWiki\User\UserEditTracker;
use MediaWiki\User\UserGroupManager;
use MediaWiki\User\UserIdentity;
use MediaWiki\User\UserNameUtils;
use MessageCache;
use ParserCache;
use Psr\Log\LoggerInterface;
use Wikimedia\Assert\Assert;
use Wikimedia\Rdbms\ILBFactory;
use WikiPage;
/**
* A factory for PageUpdater instances.
*
* @since 1.37
* @ingroup Page
*/
class PageUpdaterFactory {
/**
* Options that have to be present in the ServiceOptions object passed to the constructor.
* @note must include PageUpdater::CONSTRUCTOR_OPTIONS
* @internal
*/
public const CONSTRUCTOR_OPTIONS = [
'ArticleCountMethod',
'RCWatchCategoryMembership',
'PageCreationLog',
'AjaxEditStash',
'UseAutomaticEditSummaries',
'ManualRevertSearchRadius',
'UseRCPatrol',
];
/**
* @var RevisionStore
*/
private $revisionStore;
/**
* @var RevisionRenderer
*/
private $revisionRenderer;
/**
* @var SlotRoleRegistry
*/
private $slotRoleRegistry;
/**
* @var ParserCache
*/
private $parserCache;
/**
* @var JobQueueGroup
*/
private $jobQueueGroup;
/**
* @var MessageCache
*/
private $messageCache;
/**
* @var Language
*/
private $contLang;
/**
* @var ILBFactory
*/
private $loadbalancerFactory;
/**
* @var IContentHandlerFactory
*/
private $contentHandlerFactory;
/**
* @var HookContainer
*/
private $hookContainer;
/**
* @var EditResultCache
*/
private $editResultCache;
/**
* @var UserNameUtils
*/
private $userNameUtils;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var ServiceOptions
*/
private $options;
/** @var UserEditTracker */
private $userEditTracker;
/** @var UserGroupManager */
private $userGroupManager;
/** @var string[] */
private $softwareTags;
/**
* @param RevisionStore $revisionStore
* @param RevisionRenderer $revisionRenderer
* @param SlotRoleRegistry $slotRoleRegistry
* @param ParserCache $parserCache
* @param JobQueueGroup $jobQueueGroup
* @param MessageCache $messageCache
* @param Language $contLang
* @param ILBFactory $loadbalancerFactory
* @param IContentHandlerFactory $contentHandlerFactory
* @param HookContainer $hookContainer
* @param EditResultCache $editResultCache
* @param UserNameUtils $userNameUtils
* @param LoggerInterface $logger
* @param ServiceOptions $options
* @param UserEditTracker $userEditTracker
* @param UserGroupManager $userGroupManager
* @param string[] $softwareTags
*/
public function __construct(
RevisionStore $revisionStore,
RevisionRenderer $revisionRenderer,
SlotRoleRegistry $slotRoleRegistry,
ParserCache $parserCache,
JobQueueGroup $jobQueueGroup,
MessageCache $messageCache,
Language $contLang,
ILBFactory $loadbalancerFactory,
IContentHandlerFactory $contentHandlerFactory,
HookContainer $hookContainer,
EditResultCache $editResultCache,
UserNameUtils $userNameUtils,
LoggerInterface $logger,
ServiceOptions $options,
UserEditTracker $userEditTracker,
UserGroupManager $userGroupManager,
array $softwareTags
) {
$options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
$this->revisionStore = $revisionStore;
$this->revisionRenderer = $revisionRenderer;
$this->slotRoleRegistry = $slotRoleRegistry;
$this->parserCache = $parserCache;
$this->jobQueueGroup = $jobQueueGroup;
$this->messageCache = $messageCache;
$this->contLang = $contLang;
$this->loadbalancerFactory = $loadbalancerFactory;
$this->contentHandlerFactory = $contentHandlerFactory;
$this->hookContainer = $hookContainer;
$this->editResultCache = $editResultCache;
$this->userNameUtils = $userNameUtils;
$this->logger = $logger;
$this->options = $options;
$this->userEditTracker = $userEditTracker;
$this->userGroupManager = $userGroupManager;
$this->softwareTags = $softwareTags;
}
/**
* Return a PageUpdater for building an update to a page.
*
* @internal For now, most code should keep using WikiPage::newPageUpdater() instead.
* @note We can only start using this method everywhere when WikiPage::prepareContentForEdit()
* and WikiPage::getCurrentUpdate() have been removed. For now, the WikiPage instance is
* used to make the state of an ongoing edit available to hook handlers.
*
* @param WikiPage $page
* @param UserIdentity $user
*
* @return PageUpdater
* @since 1.37
*/
public function newPageUpdater(
WikiPage $page,
UserIdentity $user
): PageUpdater {
return $this->newPageUpdaterForDerivedPageDataUpdater(
$page,
$user,
$this->newDerivedPageDataUpdater( $page )
);
}
/**
* Return a PageUpdater for building an update to a page, reusing the state of
* an existing DerivedPageDataUpdater.
*
* @param WikiPage $page
* @param UserIdentity $user
* @param DerivedPageDataUpdater $derivedPageDataUpdater
*
* @return PageUpdater
* @internal needed by WikiPage to back the WikiPage::newPageUpdater method.
*
* @since 1.37
*/
public function newPageUpdaterForDerivedPageDataUpdater(
WikiPage $page,
UserIdentity $user,
DerivedPageDataUpdater $derivedPageDataUpdater
): PageUpdater {
Assert::precondition(
$page->canExist(),
'The WikiPage instance does not represent a proper page!'
);
$pageUpdater = new PageUpdater(
$user,
$page, // NOTE: eventually, PageUpdater should not know about WikiPage
$derivedPageDataUpdater,
$this->loadbalancerFactory->getMainLB(),
$this->revisionStore,
$this->slotRoleRegistry,
$this->contentHandlerFactory,
$this->hookContainer,
$this->userEditTracker,
$this->userGroupManager,
new ServiceOptions(
PageUpdater::CONSTRUCTOR_OPTIONS,
$this->options
),
$this->softwareTags
);
$pageUpdater->setUsePageCreationLog( $this->options->get( 'PageCreationLog' ) );
$pageUpdater->setAjaxEditStash( $this->options->get( 'AjaxEditStash' ) );
$pageUpdater->setUseAutomaticEditSummaries(
$this->options->get( 'UseAutomaticEditSummaries' )
);
return $pageUpdater;
}
/**
* @param WikiPage $page
*
* @return DerivedPageDataUpdater
* @internal Needed by WikiPage to back the deprecated prepareContentForEdit() method.
* @note Avoid direct usage of DerivedPageDataUpdater.
* @see docs/pageupdater.md for more information.
*/
public function newDerivedPageDataUpdater( WikiPage $page ): DerivedPageDataUpdater {
$derivedDataUpdater = new DerivedPageDataUpdater(
$page, // NOTE: eventually, PageUpdater should not know about WikiPage
$this->revisionStore,
$this->revisionRenderer,
$this->slotRoleRegistry,
$this->parserCache,
$this->jobQueueGroup,
$this->messageCache,
$this->contLang,
$this->loadbalancerFactory,
$this->contentHandlerFactory,
$this->hookContainer,
$this->editResultCache,
$this->userNameUtils
);
$derivedDataUpdater->setLogger( $this->logger );
$derivedDataUpdater->setArticleCountMethod( $this->options->get( 'ArticleCountMethod' ) );
$derivedDataUpdater->setRcWatchCategoryMembership(
$this->options->get( 'RCWatchCategoryMembership' )
);
return $derivedDataUpdater;
}
}

View file

@ -32,7 +32,7 @@ class ServiceOptions {
* @stable to call since 1.36
*
* @param string[] $keys Which keys to extract from $sources
* @param Config|array ...$sources Each source is either a Config object or an array. If the
* @param Config|ServiceOptions|array ...$sources Each source is either a Config object or an array. If the
* same key is present in two sources, the first one takes precedence. Keys that are not in
* $keys are ignored.
* @throws InvalidArgumentException if one of $keys is not found in any of $sources
@ -46,6 +46,11 @@ class ServiceOptions {
$this->options[$key] = $source->get( $key );
continue 2;
}
} elseif ( $source instanceof ServiceOptions ) {
if ( array_key_exists( $key, $source->options ) ) {
$this->options[$key] = $source->get( $key );
continue 2;
}
} else {
if ( array_key_exists( $key, $source ) ) {
$this->options[$key] = $source[$key];

View file

@ -41,7 +41,7 @@ use Wikimedia\ObjectFactory;
* @ingroup Content
* @since 1.35
*/
final class ContentHandlerFactory implements IContentHandlerFactory {
class ContentHandlerFactory implements IContentHandlerFactory {
/**
* @var string[]|callable[]

View file

@ -20,7 +20,6 @@
* @file
*/
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Content\ContentHandlerFactory;
use MediaWiki\Content\IContentHandlerFactory;
use MediaWiki\DAO\WikiAwareEntityTrait;
@ -38,11 +37,10 @@ use MediaWiki\Permissions\Authority;
use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Revision\RevisionStore;
use MediaWiki\Revision\SlotRecord;
use MediaWiki\Revision\SlotRoleRegistry;
use MediaWiki\Storage\DerivedPageDataUpdater;
use MediaWiki\Storage\EditResult;
use MediaWiki\Storage\EditResultCache;
use MediaWiki\Storage\PageUpdater;
use MediaWiki\Storage\PageUpdaterFactory;
use MediaWiki\Storage\RevisionSlotsUpdate;
use MediaWiki\User\UserIdentity;
use Wikimedia\Assert\Assert;
@ -260,6 +258,13 @@ class WikiPage implements Page, IDBAccessObject, PageRecord {
}
}
/**
* @return PageUpdaterFactory
*/
private function getPageUpdaterFactory(): PageUpdaterFactory {
return MediaWikiServices::getInstance()->getPageUpdaterFactory();
}
/**
* @return RevisionStore
*/
@ -267,13 +272,6 @@ class WikiPage implements Page, IDBAccessObject, PageRecord {
return MediaWikiServices::getInstance()->getRevisionStore();
}
/**
* @return SlotRoleRegistry
*/
private function getSlotRoleRegistry() {
return MediaWikiServices::getInstance()->getSlotRoleRegistry();
}
/**
* @return ContentHandlerFactory
*/
@ -1714,45 +1712,6 @@ class WikiPage implements Page, IDBAccessObject, PageRecord {
return $flags;
}
/**
* @return DerivedPageDataUpdater
*/
private function newDerivedDataUpdater() {
global $wgRCWatchCategoryMembership, $wgArticleCountMethod;
$services = MediaWikiServices::getInstance();
$editResultCache = new EditResultCache(
$services->getMainObjectStash(),
$services->getDBLoadBalancer(),
new ServiceOptions(
EditResultCache::CONSTRUCTOR_OPTIONS,
$services->getMainConfig()
)
);
$derivedDataUpdater = new DerivedPageDataUpdater(
$this, // NOTE: eventually, PageUpdater should not know about WikiPage
$this->getRevisionStore(),
$services->getRevisionRenderer(),
$this->getSlotRoleRegistry(),
$services->getParserCache(),
JobQueueGroup::singleton(),
$services->getMessageCache(),
$services->getContentLanguage(),
$services->getDBLoadBalancerFactory(),
$this->getContentHandlerFactory(),
$this->getHookContainer(),
$editResultCache,
$services->getUserNameUtils()
);
$derivedDataUpdater->setLogger( LoggerFactory::getInstance( 'SaveParse' ) );
$derivedDataUpdater->setRcWatchCategoryMembership( $wgRCWatchCategoryMembership );
$derivedDataUpdater->setArticleCountMethod( $wgArticleCountMethod );
return $derivedDataUpdater;
}
/**
* Returns a DerivedPageDataUpdater for use with the given target revision or new content.
* This method attempts to re-use the same DerivedPageDataUpdater instance for subsequent calls.
@ -1815,7 +1774,8 @@ class WikiPage implements Page, IDBAccessObject, PageRecord {
}
if ( !$this->derivedDataUpdater ) {
$this->derivedDataUpdater = $this->newDerivedDataUpdater();
$this->derivedDataUpdater =
$this->getPageUpdaterFactory()->newDerivedPageDataUpdater( $this );
}
return $this->derivedDataUpdater;
@ -1830,40 +1790,27 @@ class WikiPage implements Page, IDBAccessObject, PageRecord {
*
* @since 1.32
*
* @param Authority $performer
* @note Once extensions no longer rely on WikiPage to get access to the state of an ongoing
* edit via prepareContentForEdit() and WikiPage::getCurrentUpdate(),
* this method should be deprecated and callers should be migrated to using
* PageUpdaterFactory::newPageUpdater() instead.
*
* @param Authority|UserIdentity $performer
* @param RevisionSlotsUpdate|null $forUpdate If given, allows any cached ParserOutput
* that may already have been returned via getDerivedDataUpdater to be re-used.
*
* @return PageUpdater
*/
public function newPageUpdater( Authority $performer, RevisionSlotsUpdate $forUpdate = null ) {
$this->assertProperPage();
public function newPageUpdater( $performer, RevisionSlotsUpdate $forUpdate = null ) {
if ( $performer instanceof Authority ) {
// TODO: Deprecate this. But better get rid of this method entirely.
$performer = $performer->getUser();
}
$mwServices = MediaWikiServices::getInstance();
$config = $mwServices->getMainConfig();
$pageUpdater = new PageUpdater(
$pageUpdater = $this->getPageUpdaterFactory()->newPageUpdaterForDerivedPageDataUpdater(
$this,
$performer,
$this, // NOTE: eventually, PageUpdater should not know about WikiPage
$this->getDerivedDataUpdater( $performer->getUser(), null, $forUpdate, true ),
$this->getDBLoadBalancer(),
$this->getRevisionStore(),
$this->getSlotRoleRegistry(),
$this->getContentHandlerFactory(),
$this->getHookContainer(),
$mwServices->getUserEditTracker(),
$mwServices->getUserGroupManager(),
new ServiceOptions(
PageUpdater::CONSTRUCTOR_OPTIONS,
$config
),
ChangeTags::getSoftwareTags()
);
$pageUpdater->setUsePageCreationLog( $config->get( 'PageCreationLog' ) );
$pageUpdater->setAjaxEditStash( $config->get( 'AjaxEditStash' ) );
$pageUpdater->setUseAutomaticEditSummaries(
$config->get( 'UseAutomaticEditSummaries' )
$this->getDerivedDataUpdater( $performer, null, $forUpdate, true )
);
return $pageUpdater;

View file

@ -0,0 +1,110 @@
<?php
namespace MediaWiki\Tests\Storage;
use JobQueueGroup;
use Language;
use LoadBalancer;
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Content\ContentHandlerFactory;
use MediaWiki\HookContainer\HookContainer;
use MediaWiki\Revision\RevisionRenderer;
use MediaWiki\Revision\RevisionStore;
use MediaWiki\Revision\SlotRoleRegistry;
use MediaWiki\Storage\DerivedPageDataUpdater;
use MediaWiki\Storage\EditResultCache;
use MediaWiki\Storage\PageUpdater;
use MediaWiki\Storage\PageUpdaterFactory;
use MediaWiki\User\UserEditTracker;
use MediaWiki\User\UserGroupManager;
use MediaWiki\User\UserIdentityValue;
use MediaWiki\User\UserNameUtils;
use MediaWikiUnitTestCase;
use MessageCache;
use ParserCache;
use Psr\Log\LoggerInterface;
use Wikimedia\Rdbms\LBFactory;
use WikiPage;
/**
* @covers MediaWiki\Storage\PageUpdaterFactory
* @group Database
*/
class PageUpdaterFactoryTest extends MediaWikiUnitTestCase {
private function getPageUpdaterFactory() {
$config = [
'ArticleCountMethod' => null,
'RCWatchCategoryMembership' => null,
'PageCreationLog' => null,
'AjaxEditStash' => null,
'UseAutomaticEditSummaries' => null,
'ManualRevertSearchRadius' => null,
'UseRCPatrol' => null,
];
$lb = $this->createNoOpMock( LoadBalancer::class );
$lbFactory = $this->createNoOpMock( LBFactory::class, [ 'getMainLB' ] );
$lbFactory->method( 'getMainLB' )->willReturn( $lb );
return new PageUpdaterFactory(
$this->createNoOpMock( RevisionStore::class ),
$this->createNoOpMock( RevisionRenderer::class ),
$this->createNoOpMock( SlotRoleRegistry::class ),
$this->createNoOpMock( ParserCache::class ),
$this->createNoOpMock( JobQueueGroup::class ),
$this->createNoOpMock( MessageCache::class ),
$this->createNoOpMock( Language::class ),
$lbFactory,
$this->createNoOpMock( ContentHandlerFactory::class ),
$this->createNoOpMock( HookContainer::class ),
$this->createNoOpMock( EditResultCache::class ),
$this->createNoOpMock( UserNameUtils::class ),
$this->createNoOpMock( LoggerInterface::class ),
new ServiceOptions(
PageUpdaterFactory::CONSTRUCTOR_OPTIONS,
$config
),
$this->createNoOpMock( UserEditTracker::class ),
$this->createNoOpMock( UserGroupManager::class ),
[]
);
}
public function testNewDerivedPageDataUpdater() {
$page = $this->createNoOpMock( WikiPage::class );
$factory = $this->getPageUpdaterFactory();
$derivedPageDataUpdater = $factory->newDerivedPageDataUpdater( $page );
$this->assertInstanceOf( DerivedPageDataUpdater::class, $derivedPageDataUpdater );
}
public function testNewPageUpdater() {
$page = $this->createNoOpMock( WikiPage::class, [ 'canExist' ] );
$page->method( 'canExist' )->willReturn( true );
$user = new UserIdentityValue( 0, 'Dummy' );
$factory = $this->getPageUpdaterFactory();
$pageUpdater = $factory->newPageUpdater( $page, $user );
$this->assertInstanceOf( PageUpdater::class, $pageUpdater );
}
public function testNewPageUpdaterForDerivedPageDataUpdater() {
$page = $this->createNoOpMock( WikiPage::class, [ 'canExist' ] );
$page->method( 'canExist' )->willReturn( true );
$user = new UserIdentityValue( 0, 'Dummy' );
$factory = $this->getPageUpdaterFactory();
$derivedPageDataUpdater = $factory->newDerivedPageDataUpdater( $page );
$pageUpdater = $factory->newPageUpdaterForDerivedPageDataUpdater(
$page,
$user,
$derivedPageDataUpdater
);
$this->assertInstanceOf( PageUpdater::class, $pageUpdater );
}
}

View file

@ -42,12 +42,17 @@ class ServiceOptionsTest extends MediaWikiUnitTestCase {
[ 'a', 'b' ],
new HashConfig( [ 'a' => 'aval', 'b' => 'bval', 'c' => 'cval' ] ),
],
'Simple ServiceOptions source' => [
[ 'a' => 'aval', 'b' => 'bval' ],
[ 'a', 'b' ],
new ServiceOptions( [ 'a', 'b', 'c' ], [ 'a' => 'aval', 'b' => 'bval', 'c' => 'cval' ] ),
],
'Three different sources' => [
[ 'a' => 'aval', 'b' => 'bval' ],
[ 'a', 'b' ],
[ 'z' => 'zval' ],
new HashConfig( [ 'a' => 'aval', 'c' => 'cval' ] ),
[ 'b' => 'bval', 'd' => 'dval' ],
new ServiceOptions( [ 'b', 'd' ], [ 'b' => 'bval', 'd' => 'dval' ] ),
],
'null key' => [
[ 'a' => null ],