Merge "Inject services into SpecialWatchlist/SpecialEditWatchlist"

This commit is contained in:
jenkins-bot 2020-11-24 19:16:53 +00:00 committed by Gerrit Code Review
commit a27e2f17c2
5 changed files with 122 additions and 55 deletions

View file

@ -463,7 +463,12 @@ class SpecialPageFactory {
'EditWatchlist' => [
'class' => \SpecialEditWatchlist::class,
'services' => [
'WatchedItemStore'
'WatchedItemStore',
'TitleParser',
'GenderCache',
'LinkBatchFactory',
'NamespaceInfo',
'WikiPageFactory',
]
],
'PasswordPolicies' => [
@ -493,7 +498,16 @@ class SpecialPageFactory {
'ActorMigration',
]
],
'Watchlist' => \SpecialWatchlist::class,
'Watchlist' => [
'class' => \SpecialWatchlist::class,
'services' => [
'WatchedItemStore',
'WatchlistNotificationManager',
'PermissionManager',
'DBLoadBalancer',
'UserOptionsLookup',
]
],
'Newpages' => [
'class' => \SpecialNewpages::class,
'services' => [

View file

@ -26,9 +26,11 @@
* @ingroup Watchlist
*/
use MediaWiki\Cache\LinkBatchFactory;
use MediaWiki\Linker\LinkRenderer;
use MediaWiki\Linker\LinkTarget;
use MediaWiki\MediaWikiServices;
use MediaWiki\Page\WikiPageFactory;
/**
* Provides the UI through which users can perform editing
@ -53,33 +55,53 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
private $badItems = [];
/**
* @var TitleParser
*/
/** @var TitleParser */
private $titleParser;
/**
* @var WatchedItemStoreInterface
*/
/** @var WatchedItemStoreInterface */
private $watchedItemStore;
/** @var GenderCache */
private $genderCache;
/** @var LinkBatchFactory */
private $linkBatchFactory;
/** @var NamespaceInfo */
private $nsInfo;
/** @var WikiPageFactory */
private $wikiPageFactory;
/** @var bool Watchlist Expiry flag */
private $isWatchlistExpiryEnabled;
public function __construct( WatchedItemStoreInterface $watchedItemStore ) {
parent::__construct( 'EditWatchlist', 'editmywatchlist' );
$this->watchedItemStore = $watchedItemStore;
$this->isWatchlistExpiryEnabled = $this->getConfig()->get( 'WatchlistExpiry' );
}
/**
* Initialize any services we'll need (unless it has already been provided via a setter).
* This allows for dependency injection even though we don't control object creation.
* @param WatchedItemStoreInterface|null $watchedItemStore
* @param TitleParser|null $titleParser
* @param GenderCache|null $genderCache
* @param LinkBatchFactory|null $linkBatchFactory
* @param NamespaceInfo|null $nsInfo
* @param WikiPageFactory|null $wikiPageFactory
*/
private function initServices() {
if ( !$this->titleParser ) {
$this->titleParser = MediaWikiServices::getInstance()->getTitleParser();
}
public function __construct(
WatchedItemStoreInterface $watchedItemStore = null,
TitleParser $titleParser = null,
GenderCache $genderCache = null,
LinkBatchFactory $linkBatchFactory = null,
NamespaceInfo $nsInfo = null,
WikiPageFactory $wikiPageFactory = null
) {
parent::__construct( 'EditWatchlist', 'editmywatchlist' );
// This class is extended and therefor fallback to global state - T266065
$services = MediaWikiServices::getInstance();
$this->watchedItemStore = $watchedItemStore ?? $services->getWatchedItemStore();
$this->titleParser = $titleParser ?? $services->getTitleParser();
$this->genderCache = $genderCache ?? $services->getGenderCache();
$this->linkBatchFactory = $linkBatchFactory ?? $services->getLinkBatchFactory();
$this->nsInfo = $nsInfo ?? $services->getNamespaceInfo();
$this->wikiPageFactory = $wikiPageFactory ?? $services->getWikiPageFactory();
$this->isWatchlistExpiryEnabled = $this->getConfig()->get( 'WatchlistExpiry' );
}
public function doesWrites() {
@ -92,7 +114,6 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
* @param int $mode
*/
public function execute( $mode ) {
$this->initServices();
$this->setHeaders();
# Anons don't get a watchlist
@ -212,7 +233,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
}
}
MediaWikiServices::getInstance()->getGenderCache()->doTitlesArray( $titles );
$this->genderCache->doTitlesArray( $titles );
$list = [];
/** @var Title $title */
@ -328,8 +349,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
private function showTitles( $titles, &$output ) {
$talk = $this->msg( 'talkpagelinktext' )->text();
// Do a batch existence check
$linkBatchFactory = MediaWikiServices::getInstance()->getLinkBatchFactory();
$batch = $linkBatchFactory->newLinkBatch();
$batch = $this->linkBatchFactory->newLinkBatch();
if ( count( $titles ) >= 100 ) {
$output = $this->msg( 'watchlistedit-too-many' )->parse();
return;
@ -398,7 +418,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
}
}
MediaWikiServices::getInstance()->getGenderCache()->doTitlesArray( $titles );
$this->genderCache->doTitlesArray( $titles );
foreach ( $titles as $title ) {
$list[] = $title->getPrefixedText();
@ -418,7 +438,6 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
*/
protected function getWatchlistInfo() {
$titles = [];
$services = MediaWikiServices::getInstance();
$options = [ 'sort' => WatchedItemStore::SORT_ASC ];
if ( $this->isWatchlistExpiryEnabled ) {
@ -429,15 +448,14 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
$this->getUser(), $options
);
$linkBatchFactory = $services->getLinkBatchFactory();
$lb = $linkBatchFactory->newLinkBatch();
$lb = $this->linkBatchFactory->newLinkBatch();
$context = $this->getContext();
foreach ( $watchedItems as $watchedItem ) {
$namespace = $watchedItem->getLinkTarget()->getNamespace();
$dbKey = $watchedItem->getLinkTarget()->getDBkey();
$lb->add( $namespace, $dbKey );
if ( !$services->getNamespaceInfo()->isTalk( $namespace ) ) {
if ( !$this->nsInfo->isTalk( $namespace ) ) {
$titles[$namespace][$dbKey] = $watchedItem->getExpiryInDaysText( $context );
}
}
@ -547,7 +565,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
$title = $target instanceof LinkTarget ?
Title::newFromLinkTarget( $target ) :
Title::newFromText( $target );
$page = WikiPage::factory( $title );
$page = $this->wikiPageFactory->newFromTitle( $title );
$user = $this->getUser();
if ( $action === 'Watch' ) {
$this->getHookRunner()->onWatchArticleComplete( $user, $page );
@ -564,7 +582,6 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
*/
private function getExpandedTargets( array $targets ) {
$expandedTargets = [];
$services = MediaWikiServices::getInstance();
foreach ( $targets as $target ) {
if ( !$target instanceof LinkTarget ) {
try {
@ -578,9 +595,9 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
$ns = $target->getNamespace();
$dbKey = $target->getDBkey();
$expandedTargets[] =
new TitleValue( $services->getNamespaceInfo()->getSubject( $ns ), $dbKey );
new TitleValue( $this->nsInfo->getSubject( $ns ), $dbKey );
$expandedTargets[] =
new TitleValue( $services->getNamespaceInfo()->getTalk( $ns ), $dbKey );
new TitleValue( $this->nsInfo->getTalk( $ns ), $dbKey );
}
return $expandedTargets;
}

View file

@ -21,9 +21,11 @@
* @ingroup SpecialPage
*/
use MediaWiki\MediaWikiServices;
use MediaWiki\Permissions\PermissionManager;
use MediaWiki\User\UserOptionsLookup;
use MediaWiki\User\WatchlistNotificationManager;
use Wikimedia\Rdbms\IDatabase;
use Wikimedia\Rdbms\ILoadBalancer;
use Wikimedia\Rdbms\IResultWrapper;
/**
@ -41,8 +43,17 @@ class SpecialWatchlist extends ChangesListSpecialPage {
/** @var float|int */
private $maxDays;
/** @var WatchedItemStore */
private $watchStore;
/** @var WatchedItemStoreInterface */
private $watchedItemStore;
/** @var WatchlistNotificationManager */
private $watchlistNotificationManager;
/** @var PermissionManager */
private $permissionManager;
/** @var ILoadBalancer */
private $loadBalancer;
/** @var UserOptionsLookup */
private $userOptionsLookup;
@ -50,14 +61,28 @@ class SpecialWatchlist extends ChangesListSpecialPage {
/** @var bool Watchlist Expiry flag */
private $isWatchlistExpiryEnabled;
public function __construct( $page = 'Watchlist', $restriction = 'viewmywatchlist' ) {
parent::__construct( $page, $restriction );
/**
* @param WatchedItemStoreInterface $watchedItemStore
* @param WatchlistNotificationManager $watchlistNotificationManager
* @param PermissionManager $permissionManager
* @param ILoadBalancer $loadBalancer
* @param UserOptionsLookup $userOptionsLookup
*/
public function __construct(
WatchedItemStoreInterface $watchedItemStore,
WatchlistNotificationManager $watchlistNotificationManager,
PermissionManager $permissionManager,
ILoadBalancer $loadBalancer,
UserOptionsLookup $userOptionsLookup
) {
parent::__construct( 'Watchlist', 'viewmywatchlist' );
$this->watchedItemStore = $watchedItemStore;
$this->watchlistNotificationManager = $watchlistNotificationManager;
$this->permissionManager = $permissionManager;
$this->loadBalancer = $loadBalancer;
$this->userOptionsLookup = $userOptionsLookup;
$this->maxDays = $this->getConfig()->get( 'RCMaxAge' ) / ( 3600 * 24 );
// TODO Inject services
$services = MediaWikiServices::getInstance();
$this->watchStore = $services->getWatchedItemStore();
$this->userOptionsLookup = $services->getUserOptionsLookup();
$this->isWatchlistExpiryEnabled = $this->getConfig()->get( 'WatchlistExpiry' );
}
@ -109,9 +134,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
&& $request->wasPosted()
&& $user->matchEditToken( $request->getVal( 'token' ) )
) {
MediaWikiServices::getInstance()
->getWatchlistNotificationManager()
->clearAllUserNotifications( $user );
$this->watchlistNotificationManager->clearAllUserNotifications( $user );
$output->redirect( $this->getPageTitle()->getFullURL( $opts->getChangedValues() ) );
return;
@ -405,10 +428,9 @@ class SpecialWatchlist extends ChangesListSpecialPage {
// Log entries with DELETED_ACTION must not show up unless the user has
// the necessary rights.
$permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
if ( !$permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
if ( !$this->permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
$bitmask = LogPage::DELETED_ACTION;
} elseif ( !$permissionManager->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' ) ) {
} elseif ( !$this->permissionManager->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' ) ) {
$bitmask = LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED;
} else {
$bitmask = 0;
@ -469,7 +491,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
* @return IDatabase
*/
protected function getDB() {
return wfGetDB( DB_REPLICA, 'watchlist' );
return $this->loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA, 'watchlist' );
}
public function outputFeedLinks() {
@ -529,7 +551,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
$diffInDays = null;
// Check if the watchlist expiry flag is enabled to show new tooltip message
if ( $this->isWatchlistExpiryEnabled ) {
$watchedItem = $this->watchStore->getWatchedItem( $this->getUser(), $rc->getTitle() );
$watchedItem = $this->watchedItemStore->getWatchedItem( $this->getUser(), $rc->getTitle() );
if ( $watchedItem instanceof WatchedItem && $watchedItem->getExpiry() !== null ) {
$diffInDays = $watchedItem->getExpiryInDays();
@ -585,7 +607,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
&& $this->userOptionsLookup->getBoolOption( $user, 'shownumberswatching' )
) {
$rcTitleValue = new TitleValue( (int)$obj->rc_namespace, $obj->rc_title );
$rc->numberofWatchingusers = $this->watchStore->countWatchers( $rcTitleValue );
$rc->numberofWatchingusers = $this->watchedItemStore->countWatchers( $rcTitleValue );
} else {
$rc->numberofWatchingusers = 0;
}
@ -894,7 +916,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
* @return int
*/
protected function countItems() {
$count = $this->watchStore->countWatchedItems( $this->getUser() );
$count = $this->watchedItemStore->countWatchedItems( $this->getUser() );
return floor( $count / 2 );
}
@ -913,7 +935,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
* @return string|null TS_MW timestamp of first unseen revision or null if there isn't one
*/
private function getLatestNotificationTimestamp( RecentChange $rc ) {
return $this->watchStore->getLatestNotificationTimestamp(
return $this->watchedItemStore->getLatestNotificationTimestamp(
$rc->getAttribute( 'wl_notificationtimestamp' ),
$this->getUser(),
$rc->getTitle()

View file

@ -17,8 +17,14 @@ class SpecialEditWatchlistTest extends SpecialPageTestBase {
* @return SpecialPage
*/
protected function newSpecialPage() {
$services = MediaWikiServices::getInstance();
return new SpecialEditWatchlist(
MediaWikiServices::getInstance()->getWatchedItemStore()
$services->getWatchedItemStore(),
$services->getTitleParser(),
$services->getGenderCache(),
$services->getLinkBatchFactory(),
$services->getNamespaceInfo(),
$services->getWikiPageFactory()
);
}

View file

@ -1,5 +1,6 @@
<?php
use MediaWiki\MediaWikiServices;
use Wikimedia\TestingAccessWrapper;
/**
@ -43,7 +44,14 @@ class SpecialWatchlistTest extends SpecialPageTestBase {
* @return SpecialPage
*/
protected function newSpecialPage() {
return new SpecialWatchlist();
$services = MediaWikiServices::getInstance();
return new SpecialWatchlist(
$services->getWatchedItemStore(),
$services->getWatchlistNotificationManager(),
$services->getPermissionManager(),
$services->getDBLoadBalancer(),
$services->getUserOptionsLookup()
);
}
public function testNotLoggedIn_throwsException() {