MediaWiki master
CategoryMembershipChange.php
Go to the documentation of this file.
1<?php
2
9
35
36 private const CATEGORY_ADDITION = 1;
37 private const CATEGORY_REMOVAL = -1;
38
42 private $timestamp;
43
47 private $pageTitle;
48
52 private $revision;
53
59 private $numTemplateLinks = 0;
60
64 private $newForCategorizationCallback = null;
65
67 private $backlinkCache;
68
74 public function __construct(
75 Title $pageTitle, BacklinkCache $backlinkCache, RevisionRecord $revision = null
76 ) {
77 $this->pageTitle = $pageTitle;
78 $this->revision = $revision;
79 if ( $revision === null ) {
80 $this->timestamp = wfTimestampNow();
81 } else {
82 $this->timestamp = $revision->getTimestamp();
83 }
84 $this->newForCategorizationCallback = [ RecentChange::class, 'newForCategorization' ];
85 $this->backlinkCache = $backlinkCache;
86 }
87
95 public function overrideNewForCategorizationCallback( callable $callback ) {
96 if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
97 throw new LogicException( 'Cannot override newForCategorization callback in operation.' );
98 }
99 $this->newForCategorizationCallback = $callback;
100 }
101
105 public function checkTemplateLinks() {
106 $this->numTemplateLinks = $this->backlinkCache->getNumLinks( 'templatelinks' );
107 }
108
114 public function triggerCategoryAddedNotification( Title $categoryTitle ) {
115 $this->createRecentChangesEntry( $categoryTitle, self::CATEGORY_ADDITION );
116 }
117
123 public function triggerCategoryRemovedNotification( Title $categoryTitle ) {
124 $this->createRecentChangesEntry( $categoryTitle, self::CATEGORY_REMOVAL );
125 }
126
133 private function createRecentChangesEntry( Title $categoryTitle, $type ) {
134 $this->notifyCategorization(
135 $this->timestamp,
136 $categoryTitle,
137 $this->getUser(),
138 $this->getChangeMessageText(
139 $type,
140 $this->pageTitle->getPrefixedText(),
141 $this->numTemplateLinks
142 ),
143 $this->pageTitle,
144 $this->getPreviousRevisionTimestamp(),
145 $this->revision,
146 $type === self::CATEGORY_ADDITION
147 );
148 }
149
160 private function notifyCategorization(
161 $timestamp,
162 Title $categoryTitle,
163 ?UserIdentity $user,
164 $comment,
165 Title $pageTitle,
166 $lastTimestamp,
167 $revision,
168 $added
169 ) {
170 $deleted = $revision ? $revision->getVisibility() & RevisionRecord::SUPPRESSED_USER : 0;
171 $newRevId = $revision ? $revision->getId() : 0;
172
178 $bot = 1;
179 $lastRevId = 0;
180 $ip = '';
181
182 # If no revision is given, the change was probably triggered by parser functions
183 if ( $revision !== null ) {
184 $revisionStore = MediaWikiServices::getInstance()->getRevisionStore();
185
186 $correspondingRc = $revisionStore->getRecentChange( $this->revision ) ??
187 $revisionStore->getRecentChange( $this->revision, IDBAccessObject::READ_LATEST );
188 if ( $correspondingRc !== null ) {
189 $bot = $correspondingRc->getAttribute( 'rc_bot' ) ?: 0;
190 $ip = $correspondingRc->getAttribute( 'rc_ip' ) ?: '';
191 $lastRevId = $correspondingRc->getAttribute( 'rc_last_oldid' ) ?: 0;
192 }
193 }
194
196 $rc = ( $this->newForCategorizationCallback )(
197 $timestamp,
198 $categoryTitle,
199 $user,
200 $comment,
201 $pageTitle,
202 $lastRevId,
203 $newRevId,
204 $lastTimestamp,
205 $bot,
206 $ip,
207 $deleted,
208 $added
209 );
210 $rc->save();
211 }
212
224 private function getUser(): ?UserIdentity {
225 if ( $this->revision ) {
226 $user = $this->revision->getUser( RevisionRecord::RAW );
227 if ( $user ) {
228 return $user;
229 }
230 }
231
232 $username = wfMessage( 'autochange-username' )->inContentLanguage()->text();
233
234 $user = User::newSystemUser( $username );
235 if ( $user && !$user->isRegistered() ) {
236 $user->addToDatabase();
237 }
238
239 return $user ?: null;
240 }
241
258 private function getChangeMessageText( $type, $prefixedText, $numTemplateLinks ) {
259 $array = [
260 self::CATEGORY_ADDITION => 'recentchanges-page-added-to-category',
261 self::CATEGORY_REMOVAL => 'recentchanges-page-removed-from-category',
262 ];
263
264 $msgKey = $array[$type];
265
266 if ( intval( $numTemplateLinks ) > 0 ) {
267 $msgKey .= '-bundled';
268 }
269
270 return wfMessage( $msgKey, $prefixedText )->inContentLanguage()->text();
271 }
272
279 private function getPreviousRevisionTimestamp() {
280 $rl = MediaWikiServices::getInstance()->getRevisionLookup();
281 $latestRev = $rl->getRevisionByTitle( $this->pageTitle );
282 if ( $latestRev ) {
283 $previousRev = $rl->getPreviousRevision( $latestRev );
284 if ( $previousRev ) {
285 return $previousRev->getTimestamp();
286 }
287 }
288 return null;
289 }
290
291}
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:81
triggerCategoryRemovedNotification(Title $categoryTitle)
Create a recentchanges entry for category removals.
triggerCategoryAddedNotification(Title $categoryTitle)
Create a recentchanges entry for category additions.
overrideNewForCategorizationCallback(callable $callback)
Overrides the default new for categorization callback This is intended for use while testing and will...
__construct(Title $pageTitle, BacklinkCache $backlinkCache, RevisionRecord $revision=null)
checkTemplateLinks()
Determines the number of template links for recursive link updates.
Class for fetching backlink lists, approximate backlink counts and partitions.
Service locator for MediaWiki core services.
Page revision base class.
getVisibility()
Get the deletion bitfield of the revision.
getTimestamp()
MCR migration note: this replaced Revision::getTimestamp.
getId( $wikiId=self::LOCAL)
Get revision ID.
Represents a title within MediaWiki.
Definition Title.php:78
internal since 1.36
Definition User.php:93
Interface for objects representing user identity.
isRegistered()
This must be equivalent to getId() != 0 and is provided for code readability.