MediaWiki master
CategoryMembershipChange.php
Go to the documentation of this file.
1<?php
2
10
36
37 private const CATEGORY_ADDITION = 1;
38 private const CATEGORY_REMOVAL = -1;
39
43 private $timestamp;
44
48 private $pageTitle;
49
53 private $revision;
54
60 private $numTemplateLinks = 0;
61
65 private $newForCategorizationCallback = null;
66
68 private $backlinkCache;
69
75 public function __construct(
76 Title $pageTitle, BacklinkCache $backlinkCache, RevisionRecord $revision = null
77 ) {
78 $this->pageTitle = $pageTitle;
79 $this->revision = $revision;
80 if ( $revision === null ) {
81 $this->timestamp = wfTimestampNow();
82 } else {
83 $this->timestamp = $revision->getTimestamp();
84 }
85 $this->newForCategorizationCallback = [ RecentChange::class, 'newForCategorization' ];
86 $this->backlinkCache = $backlinkCache;
87 }
88
96 public function overrideNewForCategorizationCallback( callable $callback ) {
97 if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
98 throw new LogicException( 'Cannot override newForCategorization callback in operation.' );
99 }
100 $this->newForCategorizationCallback = $callback;
101 }
102
106 public function checkTemplateLinks() {
107 $this->numTemplateLinks = $this->backlinkCache->getNumLinks( 'templatelinks' );
108 }
109
115 public function triggerCategoryAddedNotification( PageIdentity $categoryPage ) {
116 $this->createRecentChangesEntry( $categoryPage, self::CATEGORY_ADDITION );
117 }
118
124 public function triggerCategoryRemovedNotification( PageIdentity $categoryPage ) {
125 $this->createRecentChangesEntry( $categoryPage, self::CATEGORY_REMOVAL );
126 }
127
134 private function createRecentChangesEntry( PageIdentity $categoryPage, $type ) {
135 $this->notifyCategorization(
136 $this->timestamp,
137 $categoryPage,
138 $this->getUser(),
139 $this->getChangeMessageText(
140 $type,
141 $this->pageTitle->getPrefixedText(),
142 $this->numTemplateLinks
143 ),
144 $this->pageTitle,
145 $this->getPreviousRevisionTimestamp(),
146 $this->revision,
147 $type === self::CATEGORY_ADDITION
148 );
149 }
150
161 private function notifyCategorization(
162 $timestamp,
163 PageIdentity $categoryPage,
164 ?UserIdentity $user,
165 $comment,
166 PageIdentity $page,
167 $lastTimestamp,
168 $revision,
169 $added
170 ) {
171 $deleted = $revision ? $revision->getVisibility() & RevisionRecord::SUPPRESSED_USER : 0;
172 $newRevId = $revision ? $revision->getId() : 0;
173
179 $bot = 1;
180 $lastRevId = 0;
181 $ip = '';
182
183 # If no revision is given, the change was probably triggered by parser functions
184 if ( $revision !== null ) {
185 $revisionStore = MediaWikiServices::getInstance()->getRevisionStore();
186
187 $correspondingRc = $revisionStore->getRecentChange( $this->revision ) ??
188 $revisionStore->getRecentChange( $this->revision, IDBAccessObject::READ_LATEST );
189 if ( $correspondingRc !== null ) {
190 $bot = $correspondingRc->getAttribute( 'rc_bot' ) ?: 0;
191 $ip = $correspondingRc->getAttribute( 'rc_ip' ) ?: '';
192 $lastRevId = $correspondingRc->getAttribute( 'rc_last_oldid' ) ?: 0;
193 }
194 }
195
197 $rc = ( $this->newForCategorizationCallback )(
198 $timestamp,
199 $categoryPage,
200 $user,
201 $comment,
202 $page,
203 $lastRevId,
204 $newRevId,
205 $lastTimestamp,
206 $bot,
207 $ip,
208 $deleted,
209 $added
210 );
211 $rc->save();
212 }
213
225 private function getUser(): ?UserIdentity {
226 if ( $this->revision ) {
227 $user = $this->revision->getUser( RevisionRecord::RAW );
228 if ( $user ) {
229 return $user;
230 }
231 }
232
233 $username = wfMessage( 'autochange-username' )->inContentLanguage()->text();
234
235 $user = User::newSystemUser( $username );
236 if ( $user && !$user->isRegistered() ) {
237 $user->addToDatabase();
238 }
239
240 return $user ?: null;
241 }
242
259 private function getChangeMessageText( $type, $prefixedText, $numTemplateLinks ) {
260 $array = [
261 self::CATEGORY_ADDITION => 'recentchanges-page-added-to-category',
262 self::CATEGORY_REMOVAL => 'recentchanges-page-removed-from-category',
263 ];
264
265 $msgKey = $array[$type];
266
267 if ( intval( $numTemplateLinks ) > 0 ) {
268 $msgKey .= '-bundled';
269 }
270
271 return wfMessage( $msgKey, $prefixedText )->inContentLanguage()->text();
272 }
273
280 private function getPreviousRevisionTimestamp() {
281 $rl = MediaWikiServices::getInstance()->getRevisionLookup();
282 $latestRev = $rl->getRevisionByTitle( $this->pageTitle );
283 if ( $latestRev ) {
284 $previousRev = $rl->getPreviousRevision( $latestRev );
285 if ( $previousRev ) {
286 return $previousRev->getTimestamp();
287 }
288 }
289 return null;
290 }
291
292}
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
triggerCategoryAddedNotification(PageIdentity $categoryPage)
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.
triggerCategoryRemovedNotification(PageIdentity $categoryPage)
Create a recentchanges entry for category removals.
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:79
internal since 1.36
Definition User.php:93
Interface for objects (potentially) representing an editable wiki page.
Interface for objects representing user identity.
isRegistered()
This must be equivalent to getId() != 0 and is provided for code readability.