MediaWiki master
RevisionDeleteUser.php
Go to the documentation of this file.
1<?php
11
19
29
39 private static function setUsernameBitfields( $name, $userId, $op, ?IDatabase $dbw = null ) {
40 if ( !$userId || ( $op !== '|' && $op !== '&' ) ) {
41 return false;
42 }
43 if ( !$dbw instanceof IDatabase ) {
44 $dbw = MediaWikiServices::getInstance()->getConnectionProvider()->getPrimaryDatabase();
45 }
46
47 # To suppress, we OR the current bitfields with RevisionRecord::DELETED_USER
48 # to put a 1 in the username *_deleted bit. To unsuppress we AND the
49 # current bitfields with the inverse of RevisionRecord::DELETED_USER. The
50 # username bit is made to 0 (x & 0 = 0), while others are unchanged (x & 1 = x).
51 # The same goes for the sysop-restricted *_deleted bit.
52 $delUser = RevisionRecord::DELETED_USER | RevisionRecord::DELETED_RESTRICTED;
53 $delAction = LogPage::DELETED_ACTION | RevisionRecord::DELETED_RESTRICTED;
54 if ( $op === '&' ) {
55 $delUser = $dbw->bitNot( $delUser );
56 $delAction = $dbw->bitNot( $delAction );
57 }
58
59 # Normalize user name
60 $userTitle = Title::makeTitleSafe( NS_USER, $name );
61 $userDbKey = $userTitle->getDBkey();
62
63 $actorId = $dbw->newSelectQueryBuilder()
64 ->select( 'actor_id' )
65 ->from( 'actor' )
66 ->where( [ 'actor_name' => $name ] )
67 ->caller( __METHOD__ )->fetchField();
68 if ( $actorId ) {
69 # Hide name from live edits
70 $dbw->newUpdateQueryBuilder()
71 ->update( 'revision' )
72 ->set( self::buildSetBitDeletedField( 'rev_deleted', $op, $delUser, $dbw ) )
73 ->where( [ 'rev_actor' => $actorId ] )
74 ->caller( __METHOD__ )->execute();
75
76 # Hide name from deleted edits
77 $dbw->newUpdateQueryBuilder()
78 ->update( 'archive' )
79 ->set( self::buildSetBitDeletedField( 'ar_deleted', $op, $delUser, $dbw ) )
80 ->where( [ 'ar_actor' => $actorId ] )
81 ->caller( __METHOD__ )->execute();
82
83 # Hide name from logs
84 $dbw->newUpdateQueryBuilder()
85 ->update( 'logging' )
86 ->set( self::buildSetBitDeletedField( 'log_deleted', $op, $delUser, $dbw ) )
87 ->where( [ 'log_actor' => $actorId, $dbw->expr( 'log_type', '!=', 'suppress' ) ] )
88 ->caller( __METHOD__ )->execute();
89
90 # Hide name from RC
91 $dbw->newUpdateQueryBuilder()
92 ->update( 'recentchanges' )
93 ->set( self::buildSetBitDeletedField( 'rc_deleted', $op, $delUser, $dbw ) )
94 ->where( [ 'rc_actor' => $actorId ] )
95 ->caller( __METHOD__ )->execute();
96
97 $migrationStage = MediaWikiServices::getInstance()->getMainConfig()->get(
99 );
100 if ( $migrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
101 // Hide name from live images
102 $dbw->newUpdateQueryBuilder()
103 ->update( 'oldimage' )
104 ->set( self::buildSetBitDeletedField( 'oi_deleted', $op, $delUser, $dbw ) )
105 ->where( [ 'oi_actor' => $actorId ] )
106 ->caller( __METHOD__ )->execute();
107 }
108 if ( $migrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
109 // Hide name from live images
110 $dbw->newUpdateQueryBuilder()
111 ->update( 'filerevision' )
112 ->set( self::buildSetBitDeletedField( 'fr_deleted', $op, $delUser, $dbw ) )
113 ->where( [ 'fr_actor' => $actorId ] )
114 ->caller( __METHOD__ )->execute();
115 }
116
117 // Hide name from deleted images
118 $dbw->newUpdateQueryBuilder()
119 ->update( 'filearchive' )
120 ->set( self::buildSetBitDeletedField( 'fa_deleted', $op, $delUser, $dbw ) )
121 ->where( [ 'fa_actor' => $actorId ] )
122 ->caller( __METHOD__ )->execute();
123 }
124
125 # Hide log entries pointing to the user page
126 $dbw->newUpdateQueryBuilder()
127 ->update( 'logging' )
128 ->set( self::buildSetBitDeletedField( 'log_deleted', $op, $delAction, $dbw ) )
129 ->where( [
130 'log_namespace' => NS_USER,
131 'log_title' => $userDbKey,
132 $dbw->expr( 'log_type', '!=', 'suppress' )
133 ] )
134 ->caller( __METHOD__ )->execute();
135
136 # Hide RC entries pointing to the user page
137 $dbw->newUpdateQueryBuilder()
138 ->update( 'recentchanges' )
139 ->set( self::buildSetBitDeletedField( 'rc_deleted', $op, $delAction, $dbw ) )
140 ->where( [ 'rc_namespace' => NS_USER, 'rc_title' => $userDbKey, $dbw->expr( 'rc_logid', '>', 0 ) ] )
141 ->caller( __METHOD__ )->execute();
142
143 return true;
144 }
145
152 private static function buildSetBitDeletedField(
153 string $field, string $op, $value, IDatabase $dbw
154 ): array {
155 return [ $field => new RawSQLValue( $op === '&'
156 ? $dbw->bitAnd( $field, $value )
157 : $dbw->bitOr( $field, $value )
158 ) ];
159 }
160
167 public static function suppressUserName( $name, $userId, ?IDatabase $dbw = null ) {
168 return self::setUsernameBitfields( $name, $userId, '|', $dbw );
169 }
170
177 public static function unsuppressUserName( $name, $userId, ?IDatabase $dbw = null ) {
178 return self::setUsernameBitfields( $name, $userId, '&', $dbw );
179 }
180}
181
183class_alias( RevisionDeleteUser::class, 'RevisionDeleteUser' );
const SCHEMA_COMPAT_WRITE_OLD
Definition Defines.php:293
const NS_USER
Definition Defines.php:53
const SCHEMA_COMPAT_WRITE_NEW
Definition Defines.php:297
Class to simplify the use of log pages.
Definition LogPage.php:34
A class containing constants representing the names of configuration variables.
const FileSchemaMigrationStage
Name constant for the FileSchemaMigrationStage setting, for use with Config::get()
Service locator for MediaWiki core services.
static getInstance()
Returns the global default instance of the top level service locator.
Backend functions for suppressing and unsuppressing all references to a given user,...
static unsuppressUserName( $name, $userId, ?IDatabase $dbw=null)
static suppressUserName( $name, $userId, ?IDatabase $dbw=null)
Page revision base class.
Represents a title within MediaWiki.
Definition Title.php:69
Raw SQL value to be used in query builders.
Interface to a relational database.
Definition IDatabase.php:31
bitOr( $fieldLeft, $fieldRight)
bitAnd( $fieldLeft, $fieldRight)