MediaWiki master
ChangeTrackingEventIngress.php
Go to the documentation of this file.
1<?php
2
4
19use RecentChange;
20
28
33 public const EVENTS = [
34 PageUpdatedEvent::TYPE
35 ];
36
44 public const OBJECT_SPEC = [
45 'class' => self::class,
46 'services' => [ // see __construct
47 'ChangeTagsStore',
48 'UserEditTracker',
49 'PermissionManager',
50 'WikiPageFactory',
51 'HookContainer',
52 'UserNameUtils',
53 'TalkPageNotificationManager'
54 ],
55 'events' => [ // see registerListeners()
56 PageUpdatedEvent::TYPE
57 ],
58 ];
59
60 private ChangeTagsStore $changeTagsStore;
61 private UserEditTracker $userEditTracker;
62 private PermissionManager $permissionManager;
63 private WikiPageFactory $wikiPageFactory;
64 private HookRunner $hookRunner;
65 private UserNameUtils $userNameUtils;
66 private TalkPageNotificationManager $talkPageNotificationManager;
67
68 public function __construct(
69 ChangeTagsStore $changeTagsStore,
70 UserEditTracker $userEditTracker,
71 PermissionManager $permissionManager,
72 WikiPageFactory $wikiPageFactory,
73 HookContainer $hookContainer,
74 UserNameUtils $userNameUtils,
75 TalkPageNotificationManager $talkPageNotificationManager
76 ) {
77 // NOTE: keep in sync with self::OBJECT_SPEC
78 $this->changeTagsStore = $changeTagsStore;
79 $this->userEditTracker = $userEditTracker;
80 $this->permissionManager = $permissionManager;
81 $this->wikiPageFactory = $wikiPageFactory;
82 $this->hookRunner = new HookRunner( $hookContainer );
83 $this->userNameUtils = $userNameUtils;
84 $this->talkPageNotificationManager = $talkPageNotificationManager;
85 }
86
87 public static function newForTesting(
88 ChangeTagsStore $changeTagsStore,
89 UserEditTracker $userEditTracker,
90 PermissionManager $permissionManager,
91 WikiPageFactory $wikiPageFactory,
92 HookContainer $hookContainer,
93 UserNameUtils $userNameUtils,
94 TalkPageNotificationManager $talkPageNotificationManager
95 ) {
96 $ingress = new self(
97 $changeTagsStore,
98 $userEditTracker,
99 $permissionManager,
100 $wikiPageFactory,
101 $hookContainer,
102 $userNameUtils,
103 $talkPageNotificationManager
104 );
105 $ingress->initSubscriber( self::OBJECT_SPEC );
106 return $ingress;
107 }
108
116 if ( $event->isRevisionChange()
117 && !$event->isSilent()
118 ) {
119 $this->updateRecentChangesAfterPageUpdated(
120 $event->getNewRevision(),
121 $event->getOldRevision(),
122 $event->isBotUpdate(),
123 $event->getPatrolStatus(),
124 $event->getTags(),
125 $event->getEditResult()
126 );
127 } elseif ( $event->getTags() ) {
128 $this->updateChangeTagsAfterPageUpdated(
129 $event->getTags(),
130 $event->getNewRevision()->getId(),
131 );
132 }
133
134 if ( $event->isContentChange()
135 && !$event->isAutomated()
136 ) {
137 $this->updateUserEditTrackerAfterPageUpdated(
138 $event->getPerformer()
139 );
140 }
141
142 $this->updateNewTalkAfterPageUpdated( $event );
143 }
144
145 private function updateChangeTagsAfterPageUpdated( array $tags, int $revId ) {
146 $this->changeTagsStore->addTags( $tags, null, $revId );
147 }
148
149 private function updateRecentChangesAfterPageUpdated(
150 RevisionRecord $newRevisionRecord,
151 ?RevisionRecord $oldRevisionRecord,
152 bool $forceBot,
153 int $patrolStatus,
154 array $tags,
155 ?EditResult $editResult
156 ) {
157 // Update recentchanges
158 if ( !$oldRevisionRecord ) {
159 RecentChange::notifyNew(
160 $newRevisionRecord->getTimestamp(),
161 $newRevisionRecord->getPage(),
162 $newRevisionRecord->isMinor(),
163 $newRevisionRecord->getUser( RevisionRecord::RAW ),
164 $newRevisionRecord->getComment( RevisionRecord::RAW )->text,
165 $forceBot, // $event->hasFlag( EDIT_FORCE_BOT ),
166 '',
167 $newRevisionRecord->getSize(),
168 $newRevisionRecord->getId(),
169 $patrolStatus,
170 $tags
171 );
172 } else {
173 // Add RC row to the DB
174 RecentChange::notifyEdit(
175 $newRevisionRecord->getTimestamp(),
176 $newRevisionRecord->getPage(),
177 $newRevisionRecord->isMinor(),
178 $newRevisionRecord->getUser( RevisionRecord::RAW ),
179 $newRevisionRecord->getComment( RevisionRecord::RAW )->text,
180 $oldRevisionRecord->getId(),
181 $newRevisionRecord->getTimestamp(),
182 $forceBot,
183 '',
184 $oldRevisionRecord->getSize(),
185 $newRevisionRecord->getSize(),
186 $newRevisionRecord->getId(),
187 $patrolStatus,
188 $tags,
189 $editResult
190 );
191 }
192 }
193
194 private function updateUserEditTrackerAfterPageUpdated( UserIdentity $author ) {
195 $this->userEditTracker->incrementUserEditCount( $author );
196 }
197
203 private function updateNewTalkAfterPageUpdated( PageUpdatedEvent $event ) {
204 // If this is another user's talk page, update newtalk.
205 // Don't do this if $options['changed'] = false (null-edits) nor if
206 // it's a minor edit and the user making the edit doesn't generate notifications for those.
207 $page = $event->getPage();
208 $revRecord = $event->getNewRevision();
209 $recipientName = $page->getDBkey();
210 $recipientName = $this->userNameUtils->isIP( $recipientName )
211 ? $recipientName
212 : $this->userNameUtils->getCanonical( $page->getDBkey() );
213
214 if ( $event->isContentChange()
215 && $page->getNamespace() === NS_USER_TALK
216 && !( $revRecord->isMinor()
217 && $this->permissionManager->userHasRight(
218 $event->getAuthor(), 'nominornewtalk' ) )
219 && $recipientName != $event->getAuthor()->getName()
220 ) {
221 $recipient = User::newFromName( $recipientName, false );
222 if ( !$recipient ) {
223 wfDebug( __METHOD__ . ": invalid username" );
224 } else {
225 $wikiPage = $this->wikiPageFactory->newFromTitle( $page );
226
227 // Allow extensions to prevent user notification
228 // when a new message is added to their talk page
229 // TODO: replace legacy hook! Use a listener on PageEventEmitter instead!
230 if ( $this->hookRunner->onArticleEditUpdateNewTalk( $wikiPage, $recipient ) ) {
231 if ( $this->userNameUtils->isIP( $recipientName ) ) {
232 // An anonymous user
233 $this->talkPageNotificationManager->setUserHasNewMessages( $recipient, $revRecord );
234 } elseif ( $recipient->isRegistered() ) {
235 $this->talkPageNotificationManager->setUserHasNewMessages( $recipient, $revRecord );
236 } else {
237 wfDebug( __METHOD__ . ": don't need to notify a nonexistent user" );
238 }
239 }
240 }
241 }
242 }
243
244}
const NS_USER_TALK
Definition Defines.php:68
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Read-write access to the change_tags table.
Base class for classes that implement DomainEventSubscriber.
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
getTags()
Returns any tags applied to the edit.
getPerformer()
Returns the user that performed the update.
Definition PageEvent.php:99
Domain event representing a page edit.
getPatrolStatus()
Returns the edit's initial patrol status.
getEditResult()
An EditResult representing the effects of an edit.
isContentChange()
Whether the update changed the content of the page.
isSilent()
Whether the update should be omitted from update feeds presented to the user.
isRevisionChange()
Whether this is an actual revision change, as opposed to a "null-edit" or purge.
getNewRevision()
The revision that became the current one because of the edit.
getOldRevision()
Returned the revision that used to be current before the edit.
isBotUpdate()
Whether the update was performed by a bot.
isAutomated()
Whether the update was performed automatically without the user's initiative.
Service for creating WikiPage objects.
A service class for checking permissions To obtain an instance, use MediaWikiServices::getInstance()-...
The ingress subscriber for the change tracking component.
const OBJECT_SPEC
Object spec used for lazy instantiation.
const EVENTS
The events handled by this ingress subscriber.
__construct(ChangeTagsStore $changeTagsStore, UserEditTracker $userEditTracker, PermissionManager $permissionManager, WikiPageFactory $wikiPageFactory, HookContainer $hookContainer, UserNameUtils $userNameUtils, TalkPageNotificationManager $talkPageNotificationManager)
static newForTesting(ChangeTagsStore $changeTagsStore, UserEditTracker $userEditTracker, PermissionManager $permissionManager, WikiPageFactory $wikiPageFactory, HookContainer $hookContainer, UserNameUtils $userNameUtils, TalkPageNotificationManager $talkPageNotificationManager)
handlePageUpdatedEventAfterCommit(PageUpdatedEvent $event)
Listener method for PageUpdatedEvent, to be registered with an DomainEventSource.
Page revision base class.
Object for storing information about the effects of an edit.
Track info about user edit counts and timings.
UserNameUtils service.
User class for the MediaWiki software.
Definition User.php:119
Utility class for creating and reading rows in the recentchanges table.
Interface for objects representing user identity.