29use Wikimedia\Timestamp\TimestampFormat as TS;
44 private $isEnotifEnabled;
50 private $readOnlyMode;
53 private $revisionLookup;
56 private $talkPageNotificationManager;
59 private $watchedItemStore;
68 private $wikiPageFactory;
86 private $notificationTimestampCache = [];
111 $this->hookRunner =
new HookRunner( $hookContainer );
112 $this->readOnlyMode = $readOnlyMode;
113 $this->revisionLookup = $revisionLookup;
114 $this->talkPageNotificationManager = $talkPageNotificationManager;
115 $this->watchedItemStore = $watchedItemStore;
116 $this->userFactory = $userFactory;
117 $this->nsInfo = $nsInfo;
118 $this->wikiPageFactory = $wikiPageFactory;
131 if ( $this->readOnlyMode->isReadOnly() ) {
140 if ( !$this->isEnotifEnabled ) {
141 $this->talkPageNotificationManager->removeUserHasNewMessages( $user );
145 if ( !$performer->
isAllowed(
'editmywatchlist' ) ) {
150 if ( !$user->isRegistered() ) {
154 $this->watchedItemStore->resetAllNotificationTimestampsForUser( $user );
179 if ( $this->readOnlyMode->isReadOnly() ) {
184 $userIdentity = $performer->
getUser();
187 $title->
getDBkey() === strtr( $userIdentity->getName(),
' ',
'_' )
190 if ( $userTalkPage ) {
193 } elseif ( !$oldRev ) {
194 $oldRev = $this->revisionLookup->getRevisionById( $oldid );
199 $this->talkPageNotificationManager->clearForPageView( $userIdentity, $oldRev );
202 if ( !$this->isEnotifEnabled ) {
206 if ( !$userIdentity->isRegistered() ) {
214 if ( !$performer->
isAllowed(
'editmywatchlist' ) ) {
223 $force = $userTalkPage ?
'force' :
'';
224 $this->watchedItemStore->resetNotificationTimestamp( $userIdentity, $title, $force, $oldid );
239 $cacheKey =
'u' . $user->
getId() .
'-' .
243 if ( array_key_exists( $cacheKey, $this->notificationTimestampCache ) ) {
244 return $this->notificationTimestampCache[ $cacheKey ];
247 $watchedItem = $this->watchedItemStore->getWatchedItem( $user, $title );
248 if ( $watchedItem ) {
249 $timestamp = $watchedItem->getNotificationTimestamp();
254 $this->notificationTimestampCache[ $cacheKey ] = $timestamp;
264 if ( !$this->nsInfo->
isWatchable( $target->getNamespace() ) ) {
268 if ( $target instanceof
PageIdentity && !$target->canExist() ) {
284 if ( $this->isWatchable( $target ) ) {
285 return $this->watchedItemStore->isWatched( $userIdentity, $target );
299 if ( $performer->isAllowed(
'viewmywatchlist' ) ) {
300 return $this->isWatchedIgnoringRights( $performer->
getUser(), $target );
313 if ( $this->isWatchable( $target ) ) {
314 return $this->watchedItemStore->isTempWatched( $userIdentity, $target );
328 if ( $performer->isAllowed(
'viewmywatchlist' ) ) {
329 return $this->isTempWatchedIgnoringRights( $performer->
getUser(), $target );
346 ?
string $expiry =
null
348 if ( !$this->isWatchable( $target ) ) {
349 return StatusValue::newFatal(
'watchlistnotwatchable' );
352 $wikiPage = $this->wikiPageFactory->newFromTitle( $target );
353 $title = $wikiPage->getTitle();
355 $status = Status::newFatal(
'hookaborted' );
357 if ( $this->hookRunner->onWatchArticle( $userIdentity, $wikiPage, $status, $expiry ) ) {
358 $status = StatusValue::newGood();
359 $this->watchedItemStore->addWatch( $userIdentity, $this->getSubjectPage( $title ), $expiry );
360 if ( $this->nsInfo->canHaveTalkPage( $title ) ) {
361 $this->watchedItemStore->addWatch( $userIdentity, $this->getTalkPage( $title ), $expiry );
363 $this->hookRunner->onWatchArticleComplete( $userIdentity, $wikiPage );
367 $user = $this->userFactory->newFromUserIdentity( $userIdentity );
368 $user->invalidateCache();
386 ?
string $expiry =
null
389 if ( !$performer->
isAllowed(
'editmywatchlist', $status ) ) {
393 return $this->addWatchIgnoringRights( $performer->
getUser(), $target, $expiry );
407 if ( !$this->isWatchable( $target ) ) {
408 return StatusValue::newFatal(
'watchlistnotwatchable' );
411 $wikiPage = $this->wikiPageFactory->newFromTitle( $target );
412 $title = $wikiPage->getTitle();
414 $status = Status::newFatal(
'hookaborted' );
416 if ( $this->hookRunner->onUnwatchArticle( $userIdentity, $wikiPage, $status ) ) {
417 $status = StatusValue::newGood();
418 $this->watchedItemStore->removeWatch( $userIdentity, $this->getSubjectPage( $title ) );
419 if ( $this->nsInfo->canHaveTalkPage( $title ) ) {
420 $this->watchedItemStore->removeWatch( $userIdentity, $this->getTalkPage( $title ) );
422 $this->hookRunner->onUnwatchArticleComplete( $userIdentity, $wikiPage );
426 $user = $this->userFactory->newFromUserIdentity( $userIdentity );
427 $user->invalidateCache();
438 private function getSubjectPage( PageReference $title ): PageReference {
439 if ( $this->nsInfo->isSubject( $title->getNamespace() ) ) {
442 return PageReferenceValue::localReference(
443 $this->nsInfo->getSubject( $title->getNamespace() ),
454 private function getTalkPage( PageReference $title ): PageReference {
455 if ( $this->nsInfo->isTalk( $title->getNamespace() ) ) {
458 return PageReferenceValue::localReference(
459 $this->nsInfo->getTalk( $title->getNamespace() ),
477 if ( !$performer->
isAllowed(
'editmywatchlist', $status ) ) {
481 return $this->removeWatchIgnoringRights( $performer->
getUser(), $target );
501 ?
string $expiry =
null
504 if ( !$performer->getUser()->isRegistered() || $performer->isTemp() ) {
505 return StatusValue::newGood();
511 $oldWatchedItem = $this->watchedItemStore->getWatchedItem( $performer->
getUser(), $target );
512 $changingWatchStatus = (bool)$oldWatchedItem !== $watch;
513 if ( $oldWatchedItem && $expiry !==
null ) {
515 $oldWatchPeriod = $oldWatchedItem->getExpiry() ??
'infinity';
516 $changingWatchStatus = $changingWatchStatus ||
517 $oldWatchPeriod !== ExpiryDef::normalizeExpiry( $expiry, TS::MW );
520 if ( $changingWatchStatus ) {
524 return $this->addWatchIgnoringRights( $performer->
getUser(), $target, $expiry );
526 return $this->removeWatch( $performer, $target );
if(!defined('MW_SETUP_CALLBACK'))
Service for creating WikiPage objects.
Manages user talk page notifications.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
static newGood( $value=null)
Factory function for good results.
Interface for objects (potentially) representing an editable wiki page.
canExist()
Checks whether this PageIdentity represents a "proper" page, meaning that it could exist as an editab...