mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Echo
synced 2024-11-30 10:34:54 +00:00
Use dependency injection in hooks
Removal of globals for reading config to be done in a follow-up patch Change-Id: I8652ca67375ce2f2d79de93e0a3b75ac998131e0
This commit is contained in:
parent
2ceb92f119
commit
035f39d76c
|
@ -448,7 +448,21 @@
|
|||
"main": {
|
||||
"class": "MediaWiki\\Extension\\Notifications\\Hooks",
|
||||
"services": [
|
||||
"MainConfig"
|
||||
"AuthManager",
|
||||
"CentralIdLookup",
|
||||
"MainConfig",
|
||||
"EchoAttributeManager",
|
||||
"HookContainer",
|
||||
"ContentLanguage",
|
||||
"LinkRenderer",
|
||||
"NamespaceInfo",
|
||||
"PermissionManager",
|
||||
"RevisionStore",
|
||||
"StatsdDataFactory",
|
||||
"TalkPageNotificationManager",
|
||||
"UserEditTracker",
|
||||
"UserFactory",
|
||||
"UserOptionsManager"
|
||||
]
|
||||
},
|
||||
"schema": {
|
||||
|
|
|
@ -6,15 +6,19 @@ use ApiModuleManager;
|
|||
use Config;
|
||||
use Content;
|
||||
use DeferredUpdates;
|
||||
use EchoAttributeManager;
|
||||
use EchoUserLocator;
|
||||
use EmailNotification;
|
||||
use ExtensionRegistry;
|
||||
use HTMLCheckMatrix;
|
||||
use IBufferingStatsdDataFactory;
|
||||
use Language;
|
||||
use LinksUpdate;
|
||||
use LogEntry;
|
||||
use LogicException;
|
||||
use MailAddress;
|
||||
use MediaWiki\Api\Hook\ApiMain__moduleManagerHook;
|
||||
use MediaWiki\Auth\AuthManager;
|
||||
use MediaWiki\Auth\Hook\LocalUserCreatedHook;
|
||||
use MediaWiki\DAO\WikiAwareEntity;
|
||||
use MediaWiki\Extension\Notifications\Controller\ModerationController;
|
||||
|
@ -38,11 +42,14 @@ use MediaWiki\Hook\RecentChange_saveHook;
|
|||
use MediaWiki\Hook\SendWatchlistEmailNotificationHook;
|
||||
use MediaWiki\Hook\SkinTemplateNavigation__UniversalHook;
|
||||
use MediaWiki\Hook\SpecialMuteModifyFormFieldsHook;
|
||||
use MediaWiki\HookContainer\HookContainer;
|
||||
use MediaWiki\Linker\LinkRenderer;
|
||||
use MediaWiki\Logger\LoggerFactory;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use MediaWiki\Page\Hook\ArticleDeleteCompleteHook;
|
||||
use MediaWiki\Page\Hook\ArticleUndeleteHook;
|
||||
use MediaWiki\Page\Hook\RollbackCompleteHook;
|
||||
use MediaWiki\Permissions\PermissionManager;
|
||||
use MediaWiki\Preferences\Hook\GetPreferencesHook;
|
||||
use MediaWiki\Preferences\MultiTitleFilter;
|
||||
use MediaWiki\Preferences\MultiUsernameFilter;
|
||||
|
@ -50,16 +57,23 @@ use MediaWiki\ResourceLoader as RL;
|
|||
use MediaWiki\ResourceLoader\Hook\ResourceLoaderRegisterModulesHook;
|
||||
use MediaWiki\ResourceLoader\ResourceLoader;
|
||||
use MediaWiki\Revision\RevisionRecord;
|
||||
use MediaWiki\Revision\RevisionStore;
|
||||
use MediaWiki\Storage\EditResult;
|
||||
use MediaWiki\Storage\Hook\PageSaveCompleteHook;
|
||||
use MediaWiki\Title\NamespaceInfo;
|
||||
use MediaWiki\Title\Title;
|
||||
use MediaWiki\User\CentralId\CentralIdLookup;
|
||||
use MediaWiki\User\Hook\UserClearNewTalkNotificationHook;
|
||||
use MediaWiki\User\Hook\UserGetDefaultOptionsHook;
|
||||
use MediaWiki\User\Hook\UserGroupsChangedHook;
|
||||
use MediaWiki\User\Hook\UserSaveSettingsHook;
|
||||
use MediaWiki\User\Options\Hook\LoadUserOptionsHook;
|
||||
use MediaWiki\User\Options\Hook\SaveUserOptionsHook;
|
||||
use MediaWiki\User\TalkPageNotificationManager;
|
||||
use MediaWiki\User\UserEditTracker;
|
||||
use MediaWiki\User\UserFactory;
|
||||
use MediaWiki\User\UserIdentity;
|
||||
use MediaWiki\User\UserOptionsManager;
|
||||
use MediaWiki\WikiMap\WikiMap;
|
||||
use OutputPage;
|
||||
use RecentChange;
|
||||
|
@ -98,16 +112,56 @@ class Hooks implements
|
|||
UserSaveSettingsHook,
|
||||
SpecialMuteModifyFormFieldsHook
|
||||
{
|
||||
/**
|
||||
* @var Config
|
||||
*/
|
||||
private $config;
|
||||
private AuthManager $authManager;
|
||||
private CentralIdLookup $centralIdLookup;
|
||||
private Config $config;
|
||||
private EchoAttributeManager $attributeManager;
|
||||
private HookContainer $hookContainer;
|
||||
private Language $contentLanguage;
|
||||
private LinkRenderer $linkRenderer;
|
||||
private NamespaceInfo $namespaceInfo;
|
||||
private PermissionManager $permissionManager;
|
||||
private RevisionStore $revisionStore;
|
||||
private IBufferingStatsdDataFactory $statsdDataFactory;
|
||||
private TalkPageNotificationManager $talkPageNotificationManager;
|
||||
private UserEditTracker $userEditTracker;
|
||||
private UserFactory $userFactory;
|
||||
private UserOptionsManager $userOptionsManager;
|
||||
|
||||
/** @var array */
|
||||
private static $revertedRevIds = [];
|
||||
private static array $revertedRevIds = [];
|
||||
|
||||
public function __construct( Config $config ) {
|
||||
public function __construct(
|
||||
AuthManager $authManager,
|
||||
CentralIdLookup $centralIdLookup,
|
||||
Config $config,
|
||||
EchoAttributeManager $attributeManager,
|
||||
HookContainer $hookContainer,
|
||||
Language $contentLanguage,
|
||||
LinkRenderer $linkRenderer,
|
||||
NamespaceInfo $namespaceInfo,
|
||||
PermissionManager $permissionManager,
|
||||
RevisionStore $revisionStore,
|
||||
IBufferingStatsdDataFactory $statsdDataFactory,
|
||||
TalkPageNotificationManager $talkPageNotificationManager,
|
||||
UserEditTracker $userEditTracker,
|
||||
UserFactory $userFactory,
|
||||
UserOptionsManager $userOptionsManager
|
||||
) {
|
||||
$this->authManager = $authManager;
|
||||
$this->centralIdLookup = $centralIdLookup;
|
||||
$this->config = $config;
|
||||
$this->attributeManager = $attributeManager;
|
||||
$this->hookContainer = $hookContainer;
|
||||
$this->contentLanguage = $contentLanguage;
|
||||
$this->linkRenderer = $linkRenderer;
|
||||
$this->namespaceInfo = $namespaceInfo;
|
||||
$this->permissionManager = $permissionManager;
|
||||
$this->revisionStore = $revisionStore;
|
||||
$this->statsdDataFactory = $statsdDataFactory;
|
||||
$this->talkPageNotificationManager = $talkPageNotificationManager;
|
||||
$this->userEditTracker = $userEditTracker;
|
||||
$this->userFactory = $userFactory;
|
||||
$this->userOptionsManager = $userOptionsManager;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -257,8 +311,6 @@ class Hooks implements
|
|||
$wgEchoCrossWikiNotifications, $wgEchoPerUserBlacklist,
|
||||
$wgEchoWatchlistNotifications;
|
||||
|
||||
$attributeManager = Services::getInstance()->getAttributeManager();
|
||||
|
||||
// Show email frequency options
|
||||
$freqOptions = [
|
||||
'echo-pref-email-frequency-never' => EmailFrequency::NEVER,
|
||||
|
@ -287,16 +339,15 @@ class Hooks implements
|
|||
|
||||
// Display information about the user's currently set email address
|
||||
$prefsTitle = SpecialPage::getTitleFor( 'Preferences', false, 'mw-prefsection-echo' );
|
||||
$link = MediaWikiServices::getInstance()->getLinkRenderer()->makeLink(
|
||||
$link = $this->linkRenderer->makeLink(
|
||||
SpecialPage::getTitleFor( 'ChangeEmail' ),
|
||||
wfMessage( $user->getEmail() ? 'prefs-changeemail' : 'prefs-setemail' )->text(),
|
||||
[],
|
||||
[ 'returnto' => $prefsTitle->getFullText() ]
|
||||
);
|
||||
$permManager = MediaWikiServices::getInstance()->getPermissionManager();
|
||||
$emailAddress = $user->getEmail() && $permManager->userHasRight( $user, 'viewmyprivateinfo' )
|
||||
$emailAddress = $user->getEmail() && $this->permissionManager->userHasRight( $user, 'viewmyprivateinfo' )
|
||||
? htmlspecialchars( $user->getEmail() ) : '';
|
||||
if ( $permManager->userHasRight( $user, 'editmyprivateinfo' ) && self::isEmailChangeAllowed() ) {
|
||||
if ( $this->permissionManager->userHasRight( $user, 'editmyprivateinfo' ) && $this->isEmailChangeAllowed() ) {
|
||||
if ( $emailAddress === '' ) {
|
||||
$emailAddress .= $link;
|
||||
} else {
|
||||
|
@ -329,15 +380,15 @@ class Hooks implements
|
|||
|
||||
// Sort notification categories by priority
|
||||
$categoriesAndPriorities = [];
|
||||
foreach ( $attributeManager->getInternalCategoryNames() as $category ) {
|
||||
foreach ( $this->attributeManager->getInternalCategoryNames() as $category ) {
|
||||
// See if the category should be hidden from preferences.
|
||||
if ( !$attributeManager->isCategoryDisplayedInPreferences( $category ) ) {
|
||||
if ( !$this->attributeManager->isCategoryDisplayedInPreferences( $category ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// See if user is eligible to receive this notification (per user group restrictions)
|
||||
if ( $attributeManager->getCategoryEligibility( $user, $category ) ) {
|
||||
$categoriesAndPriorities[$category] = $attributeManager->getCategoryPriority( $category );
|
||||
if ( $this->attributeManager->getCategoryEligibility( $user, $category ) ) {
|
||||
$categoriesAndPriorities[$category] = $this->attributeManager->getCategoryPriority( $category );
|
||||
}
|
||||
}
|
||||
asort( $categoriesAndPriorities );
|
||||
|
@ -375,11 +426,11 @@ class Hooks implements
|
|||
foreach ( $wgEchoNotifiers as $notifierType => $notifierData ) {
|
||||
foreach ( $validSortedCategories as $category ) {
|
||||
// See if this notify type is non-dismissable
|
||||
if ( !$attributeManager->isNotifyTypeDismissableForCategory( $category, $notifierType ) ) {
|
||||
if ( !$this->attributeManager->isNotifyTypeDismissableForCategory( $category, $notifierType ) ) {
|
||||
$forceOptionsOn[] = "$notifierType-$category";
|
||||
}
|
||||
|
||||
if ( !$attributeManager->isNotifyTypeAvailableForCategory( $category, $notifierType ) ) {
|
||||
if ( !$this->attributeManager->isNotifyTypeAvailableForCategory( $category, $notifierType ) ) {
|
||||
$forceOptionsOff[] = "$notifierType-$category";
|
||||
}
|
||||
}
|
||||
|
@ -469,9 +520,8 @@ class Hooks implements
|
|||
* Test whether email address change is supposed to be allowed
|
||||
* @return bool
|
||||
*/
|
||||
private static function isEmailChangeAllowed() {
|
||||
return MediaWikiServices::getInstance()->getAuthManager()
|
||||
->allowsPropertyChange( 'emailaddress' );
|
||||
private function isEmailChangeAllowed() {
|
||||
return $this->authManager->allowsPropertyChange( 'emailaddress' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -515,7 +565,7 @@ class Hooks implements
|
|||
// test for them reaching a congratulatory threshold
|
||||
$thresholds = [ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 ];
|
||||
if ( $userIdentity->isRegistered() ) {
|
||||
$thresholdCount = self::getEditCount( $userIdentity );
|
||||
$thresholdCount = $this->getEditCount( $userIdentity );
|
||||
if ( in_array( $thresholdCount, $thresholds ) ) {
|
||||
DeferredUpdates::addCallableUpdate( static function () use (
|
||||
$revisionRecord, $userIdentity, $title, $thresholdCount ) {
|
||||
|
@ -555,9 +605,8 @@ class Hooks implements
|
|||
// Reverts through the 'rollback' link (EditResult::REVERT_ROLLBACK)
|
||||
// are handled in ::onRollbackComplete().
|
||||
if ( $editResult->getRevertMethod() === EditResult::REVERT_UNDO ) {
|
||||
$store = MediaWikiServices::getInstance()->getRevisionStore();
|
||||
$undidRevId = $editResult->getUndidRevId();
|
||||
$undidRevision = $store->getRevisionById( $undidRevId );
|
||||
$undidRevision = $this->revisionStore->getRevisionById( $undidRevId );
|
||||
if (
|
||||
$undidRevision &&
|
||||
Title::newFromLinkTarget( $undidRevision->getPageAsLinkTarget() )->equals( $title )
|
||||
|
@ -586,9 +635,8 @@ class Hooks implements
|
|||
* @param UserIdentity $user
|
||||
* @return int
|
||||
*/
|
||||
private static function getEditCount( UserIdentity $user ) {
|
||||
$editCount = MediaWikiServices::getInstance()->getUserEditTracker()
|
||||
->getUserEditCount( $user ) ?: 0;
|
||||
private function getEditCount( UserIdentity $user ) {
|
||||
$editCount = $this->userEditTracker->getUserEditCount( $user ) ?: 0;
|
||||
// When this code runs from a maintenance script or unit tests
|
||||
// the deferred update incrementing edit count runs right away
|
||||
// so the edit count is right. Otherwise it lags by one.
|
||||
|
@ -623,9 +671,8 @@ class Hooks implements
|
|||
public function onLocalUserCreated( $user, $autocreated ) {
|
||||
if ( !$autocreated ) {
|
||||
$overrides = self::getNewUserPreferenceOverrides();
|
||||
$userOptionsManager = MediaWikiServices::getInstance()->getUserOptionsManager();
|
||||
foreach ( $overrides as $prefKey => $value ) {
|
||||
$userOptionsManager->setOption( $user, $prefKey, $value );
|
||||
$this->userOptionsManager->setOption( $user, $prefKey, $value );
|
||||
}
|
||||
Event::create( [
|
||||
'type' => 'welcome',
|
||||
|
@ -663,7 +710,7 @@ class Hooks implements
|
|||
return;
|
||||
}
|
||||
|
||||
$user = MediaWikiServices::getInstance()->getUserFactory()->newFromUserIdentity( $userId );
|
||||
$user = $this->userFactory->newFromUserIdentity( $userId );
|
||||
|
||||
if ( $user->equals( $performer ) ) {
|
||||
// Don't notify for self changes
|
||||
|
@ -729,13 +776,11 @@ class Hooks implements
|
|||
}
|
||||
}
|
||||
|
||||
$namespaceInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
|
||||
|
||||
// Handle only
|
||||
// 1. content namespace pages &&
|
||||
// 2. non-transcluding pages &&
|
||||
// 3. non-redirect pages
|
||||
if ( !$namespaceInfo->isContent( $linksUpdate->getTitle()->getNamespace() )
|
||||
if ( !$this->namespaceInfo->isContent( $linksUpdate->getTitle()->getNamespace() )
|
||||
|| !$linksUpdate->isRecursive() || $linksUpdate->getTitle()->isRedirect()
|
||||
) {
|
||||
return;
|
||||
|
@ -752,7 +797,7 @@ class Hooks implements
|
|||
// Only create notifications for links to content namespace pages
|
||||
// @Todo - use one big insert instead of individual insert inside foreach loop
|
||||
foreach ( $linksUpdate->getAddedLinks() as $title ) {
|
||||
if ( $namespaceInfo->isContent( $title->getNamespace() ) ) {
|
||||
if ( $this->namespaceInfo->isContent( $title->getNamespace() ) ) {
|
||||
if ( $title->isRedirect() ) {
|
||||
continue;
|
||||
}
|
||||
|
@ -797,7 +842,7 @@ class Hooks implements
|
|||
return;
|
||||
}
|
||||
|
||||
if ( self::shouldDisplayTalkAlert( $user, $out->getTitle() ) ) {
|
||||
if ( $this->shouldDisplayTalkAlert( $user, $out->getTitle() ) ) {
|
||||
// Load the module for the Orange alert
|
||||
$out->addModuleStyles( 'ext.echo.styles.alert' );
|
||||
}
|
||||
|
@ -898,10 +943,8 @@ class Hooks implements
|
|||
* @param Title $title
|
||||
* @return bool
|
||||
*/
|
||||
private static function shouldDisplayTalkAlert( $user, $title ) {
|
||||
$userHasNewMessages = MediaWikiServices::getInstance()
|
||||
->getTalkPageNotificationManager()
|
||||
->userHasNewMessages( $user );
|
||||
private function shouldDisplayTalkAlert( $user, $title ) {
|
||||
$userHasNewMessages = $this->talkPageNotificationManager->userHasNewMessages( $user );
|
||||
|
||||
return $userHasNewMessages && !$user->getTalkPage()->equals( $title );
|
||||
}
|
||||
|
@ -1006,9 +1049,8 @@ class Hooks implements
|
|||
$mytalk = $links['user-menu']['mytalk'] ?? false;
|
||||
if (
|
||||
$mytalk &&
|
||||
self::shouldDisplayTalkAlert( $user, $title ) &&
|
||||
( new HookRunner( MediaWikiServices::getInstance()
|
||||
->getHookContainer() ) )->onBeforeDisplayOrangeAlert( $user, $title )
|
||||
$this->shouldDisplayTalkAlert( $user, $title ) &&
|
||||
( new HookRunner( $this->hookContainer ) )->onBeforeDisplayOrangeAlert( $user, $title )
|
||||
) {
|
||||
// Create new talk alert inheriting from the talk link data.
|
||||
$links['notifications']['talk-alert'] = array_merge(
|
||||
|
@ -1072,7 +1114,7 @@ class Hooks implements
|
|||
// Record that the user is going to see an indicator that they have unseen notifications
|
||||
// This is part of tracking how likely users are to click a badge with unseen notifications.
|
||||
// The other part is the 'echo.unseen.click' counter, see ext.echo.init.js.
|
||||
MediaWikiServices::getInstance()->getStatsdDataFactory()->increment( 'echo.unseen' );
|
||||
$this->statsdDataFactory->increment( 'echo.unseen' );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1122,8 +1164,7 @@ class Hooks implements
|
|||
}
|
||||
|
||||
if ( $eventName !== false ) {
|
||||
$attributeManager = Services::getInstance()->getAttributeManager();
|
||||
$events = $attributeManager->getUserEnabledEvents( $targetUser, 'email' );
|
||||
$events = $this->attributeManager->getUserEnabledEvents( $targetUser, 'email' );
|
||||
if ( in_array( $eventName, $events ) ) {
|
||||
// Do not send watchlist email notification, the user will receive an Echo notification
|
||||
return false;
|
||||
|
@ -1180,8 +1221,7 @@ class Hooks implements
|
|||
// notifications for talk page messages, disable the new messages alert.
|
||||
if ( $user->isRegistered()
|
||||
&& isset( $wgEchoNotifications['edit-user-talk'] )
|
||||
&& ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )
|
||||
->onEchoCanAbortNewMessagesAlert()
|
||||
&& ( new HookRunner( $this->hookContainer ) )->onEchoCanAbortNewMessagesAlert()
|
||||
) {
|
||||
// hide new messages alert
|
||||
return false;
|
||||
|
@ -1358,8 +1398,7 @@ class Hooks implements
|
|||
$autoFooter = "\n\n-- \n" . wfMessage( 'emailuserfooter', $from->name, $address->name )
|
||||
->inContentLanguage()->text();
|
||||
$textWithoutFooter = preg_replace( '/' . preg_quote( $autoFooter, '/' ) . '$/', '', $text );
|
||||
$preview = MediaWikiServices::getInstance()->getContentLanguage()
|
||||
->truncateForVisual( $textWithoutFooter, 125 );
|
||||
$preview = $this->contentLanguage->truncateForVisual( $textWithoutFooter, 125 );
|
||||
} else {
|
||||
$preview = $subject;
|
||||
}
|
||||
|
@ -1440,12 +1479,11 @@ class Hooks implements
|
|||
* @param array &$fields
|
||||
*/
|
||||
public function onSpecialMuteModifyFormFields( $target, $user, &$fields ) {
|
||||
$services = MediaWikiServices::getInstance();
|
||||
$echoPerUserBlacklist = $services->getMainConfig()->get( 'EchoPerUserBlacklist' );
|
||||
$echoPerUserBlacklist = $this->config->get( 'EchoPerUserBlacklist' );
|
||||
if ( $echoPerUserBlacklist ) {
|
||||
$id = $target ? $services->getCentralIdLookup()->centralIdFromLocalUser( $target ) : 0;
|
||||
$id = $target ? $this->centralIdLookup->centralIdFromLocalUser( $target ) : 0;
|
||||
$list = MultiUsernameFilter::splitIds(
|
||||
$services->getUserOptionsLookup()->getOption( $user, 'echo-notifications-blacklist' )
|
||||
$this->userOptionsManager->getOption( $user, 'echo-notifications-blacklist' )
|
||||
);
|
||||
$fields[ 'echo-notifications-blacklist'] = [
|
||||
'type' => 'check',
|
||||
|
@ -1495,9 +1533,7 @@ class Hooks implements
|
|||
* @param ApiModuleManager $moduleManager
|
||||
*/
|
||||
public function onApiMain__ModuleManager( $moduleManager ) {
|
||||
$services = MediaWikiServices::getInstance();
|
||||
$echoConfig = $services->getConfigFactory()->makeConfig( 'Echo' );
|
||||
$pushEnabled = $echoConfig->get( 'EchoEnablePush' );
|
||||
$pushEnabled = $this->config->get( 'EchoEnablePush' );
|
||||
if ( $pushEnabled ) {
|
||||
$moduleManager->addModule(
|
||||
'echopushsubscriptions',
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
use MediaWiki\Extension\Notifications\Hooks as EchoHooks;
|
||||
use MediaWiki\Extension\Notifications\Services;
|
||||
|
||||
class EchoHooksTest extends MediaWikiIntegrationTestCase {
|
||||
/**
|
||||
|
@ -35,7 +36,8 @@ class EchoHooksTest extends MediaWikiIntegrationTestCase {
|
|||
// T174220: don't overwrite defaults set elsewhere
|
||||
'echo-subscriptions-web-mention' => false,
|
||||
];
|
||||
( new EchoHooks( new HashConfig ) )->onUserGetDefaultOptions( $defaults );
|
||||
$hooks = $this->getHooks();
|
||||
$hooks->onUserGetDefaultOptions( $defaults );
|
||||
self::assertEquals(
|
||||
[
|
||||
'something' => 'unrelated',
|
||||
|
@ -52,4 +54,26 @@ class EchoHooksTest extends MediaWikiIntegrationTestCase {
|
|||
$defaults
|
||||
);
|
||||
}
|
||||
|
||||
public function getHooks() {
|
||||
$services = $this->getServiceContainer();
|
||||
$hooks = new EchoHooks(
|
||||
$services->getAuthManager(),
|
||||
$services->getCentralIdLookup(),
|
||||
$services->getMainConfig(),
|
||||
Services::wrap( $services )->getAttributeManager(),
|
||||
$services->getHookContainer(),
|
||||
$services->getContentLanguage(),
|
||||
$services->getLinkRenderer(),
|
||||
$services->getNamespaceInfo(),
|
||||
$services->getPermissionManager(),
|
||||
$services->getRevisionStore(),
|
||||
$services->getStatsdDataFactory(),
|
||||
$services->getTalkPageNotificationManager(),
|
||||
$services->getUserEditTracker(),
|
||||
$services->getUserFactory(),
|
||||
$services->getUserOptionsManager(),
|
||||
);
|
||||
return $hooks;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue