MediaWiki master
SpecialDeletedContributions.php
Go to the documentation of this file.
1<?php
21namespace MediaWiki\Specials;
22
41use Wikimedia\IPUtils;
43
51 protected $mOpts;
52
53 private PermissionManager $permissionManager;
54 private IConnectionProvider $dbProvider;
55 private RevisionFactory $revisionFactory;
56 private NamespaceInfo $namespaceInfo;
57 private UserFactory $userFactory;
58 private UserNameUtils $userNameUtils;
59 private UserNamePrefixSearch $userNamePrefixSearch;
60 private CommentFormatter $commentFormatter;
61 private LinkBatchFactory $linkBatchFactory;
62 private DatabaseBlockStore $blockStore;
63
76 public function __construct(
77 PermissionManager $permissionManager,
78 IConnectionProvider $dbProvider,
79 RevisionFactory $revisionFactory,
80 NamespaceInfo $namespaceInfo,
81 UserFactory $userFactory,
82 UserNameUtils $userNameUtils,
83 UserNamePrefixSearch $userNamePrefixSearch,
84 CommentFormatter $commentFormatter,
85 LinkBatchFactory $linkBatchFactory,
86 DatabaseBlockStore $blockStore
87 ) {
88 parent::__construct( 'DeletedContributions', 'deletedhistory' );
89 $this->permissionManager = $permissionManager;
90 $this->dbProvider = $dbProvider;
91 $this->revisionFactory = $revisionFactory;
92 $this->namespaceInfo = $namespaceInfo;
93 $this->userFactory = $userFactory;
94 $this->userNameUtils = $userNameUtils;
95 $this->userNamePrefixSearch = $userNamePrefixSearch;
96 $this->commentFormatter = $commentFormatter;
97 $this->linkBatchFactory = $linkBatchFactory;
98 $this->blockStore = $blockStore;
99 }
100
107 public function execute( $par ) {
108 $this->setHeaders();
109 $this->outputHeader();
110 $this->checkPermissions();
111 $out = $this->getOutput();
112 $out->addModuleStyles( [
113 'mediawiki.interface.helpers.styles',
114 'mediawiki.special.changeslist',
115 ] );
116 $this->addHelpLink( 'Help:User contributions' );
117
118 $opts = new FormOptions();
119
120 $opts->add( 'target', '' );
121 $opts->add( 'namespace', '' );
122 $opts->add( 'limit', 20 );
123
124 $opts->fetchValuesFromRequest( $this->getRequest() );
125 $opts->validateIntBounds( 'limit', 0,
127
128 if ( $par !== null ) {
129 // Beautify the username
130 $par = $this->userNameUtils->getCanonical( $par, UserRigorOptions::RIGOR_NONE );
131 $opts->setValue( 'target', (string)$par );
132 }
133
134 $ns = $opts->getValue( 'namespace' );
135 if ( $ns !== null && $ns !== '' ) {
136 $opts->setValue( 'namespace', intval( $ns ) );
137 }
138
139 $this->mOpts = $opts;
140
141 $target = trim( $opts->getValue( 'target' ) );
142 if ( !strlen( $target ) ) {
143 $this->getForm();
144
145 return;
146 }
147
148 $userObj = $this->userFactory->newFromName( $target, UserRigorOptions::RIGOR_NONE );
149 if ( !$userObj ) {
150 $this->getForm();
151
152 return;
153 }
154 // Only set valid local user as the relevant user (T344886)
155 // Uses the same condition as the SpecialContributions class did
156 if ( !IPUtils::isValidRange( $target ) &&
157 ( $this->userNameUtils->isIP( $target ) || $userObj->isRegistered() )
158 ) {
159 $this->getSkin()->setRelevantUser( $userObj );
160 }
161
162 $target = $userObj->getName();
163
164 $out->addSubtitle( $this->getSubTitle( $userObj ) );
165 $out->setPageTitleMsg( $this->msg( 'deletedcontributions-title' )->plaintextParams( $target ) );
166
167 $this->getForm();
168
169 $pager = new DeletedContribsPager(
170 $this->getContext(),
171 $this->getHookContainer(),
172 $this->getLinkRenderer(),
173 $this->dbProvider,
174 $this->revisionFactory,
175 $this->commentFormatter,
176 $this->linkBatchFactory,
177 $target,
178 $opts->getValue( 'namespace' )
179 );
180 if ( !$pager->getNumRows() ) {
181 $out->addWikiMsg( 'nocontribs' );
182
183 return;
184 }
185
186 # Show a message about replica DB lag, if applicable
187 $lag = $pager->getDatabase()->getSessionLagStatus()['lag'];
188 if ( $lag > 0 ) {
189 $out->showLagWarning( $lag );
190 }
191
192 $out->addHTML(
193 '<p>' . $pager->getNavigationBar() . '</p>' .
194 $pager->getBody() .
195 '<p>' . $pager->getNavigationBar() . '</p>' );
196
197 # If there were contributions, and it was a valid user or IP, show
198 # the appropriate "footer" message - WHOIS tools, etc.
199 $message = IPUtils::isIPAddress( $target ) ?
200 'sp-contributions-footer-anon' :
201 'sp-contributions-footer';
202
203 if ( !$this->msg( $message )->isDisabled() ) {
204 $out->wrapWikiMsg(
205 "<div class='mw-contributions-footer'>\n$1\n</div>",
206 [ $message, $target ]
207 );
208 }
209 }
210
216 private function getSubTitle( $userObj ) {
217 $linkRenderer = $this->getLinkRenderer();
218 if ( $userObj->isAnon() ) {
219 $user = htmlspecialchars( $userObj->getName() );
220 } else {
221 $user = $linkRenderer->makeLink( $userObj->getUserPage(), $userObj->getName() );
222 }
223 $links = '';
224 $nt = $userObj->getUserPage();
225 $talk = $nt->getTalkPage();
226 if ( $talk ) {
228 $this,
229 $userObj,
230 $this->permissionManager,
231 $this->getHookRunner()
232 );
233
234 $contributionsLink = $linkRenderer->makeKnownLink(
235 SpecialPage::getTitleFor( 'Contributions', $nt->getDBkey() ),
236 $this->msg( 'sp-deletedcontributions-contribs' )->text()
237 );
238 if ( isset( $tools['deletedcontribs'] ) ) {
239 // Swap out the deletedcontribs link for our contribs one
240 $tools = wfArrayInsertAfter(
241 $tools, [ 'contribs' => $contributionsLink ], 'deletedcontribs' );
242 unset( $tools['deletedcontribs'] );
243 } else {
244 $tools['contribs'] = $contributionsLink;
245 }
246
247 $links = $this->getLanguage()->pipeList( $tools );
248
249 // Show a note if the user is blocked and display the last block log entry.
250 $block = $this->blockStore->newFromTarget( $userObj, $userObj );
251 if ( $block !== null && $block->getType() != Block::TYPE_AUTO ) {
252 if ( $block->getType() == Block::TYPE_RANGE ) {
253 $nt = $this->namespaceInfo->getCanonicalName( NS_USER )
254 . ':' . $block->getTargetName();
255 }
256
257 // LogEventsList::showLogExtract() wants the first parameter by ref
258 $out = $this->getOutput();
260 $out,
261 'block',
262 $nt,
263 '',
264 [
265 'lim' => 1,
266 'showIfEmpty' => false,
267 'msgKey' => [
268 'sp-contributions-blocked-notice',
269 $userObj->getName() # Support GENDER in 'sp-contributions-blocked-notice'
270 ],
271 'offset' => '' # don't use $this->getRequest() parameter offset
272 ]
273 );
274 }
275 }
276
277 return $this->msg( 'contribsub2' )->rawParams( $user, $links )->params( $userObj->getName() );
278 }
279
283 private function getForm() {
284 $opts = $this->mOpts;
285
286 $formDescriptor = [
287 'target' => [
288 'type' => 'user',
289 'name' => 'target',
290 'label-message' => 'sp-contributions-username',
291 'default' => $opts->getValue( 'target' ),
292 'ipallowed' => true,
293 ],
294
295 'namespace' => [
296 'type' => 'namespaceselect',
297 'name' => 'namespace',
298 'label-message' => 'namespace',
299 'all' => '',
300 ],
301 ];
302
303 HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
304 ->setWrapperLegendMsg( 'sp-contributions-search' )
305 ->setSubmitTextMsg( 'sp-contributions-submit' )
306 // prevent setting subpage and 'target' parameter at the same time
307 ->setTitle( $this->getPageTitle() )
308 ->setMethod( 'get' )
309 ->prepareForm()
310 ->displayForm( false );
311 }
312
321 public function prefixSearchSubpages( $search, $limit, $offset ) {
322 $search = $this->userNameUtils->getCanonical( $search );
323 if ( !$search ) {
324 // No prefix suggestion for invalid user
325 return [];
326 }
327 // Autocomplete subpage as user list - public to allow caching
328 return $this->userNamePrefixSearch
329 ->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
330 }
331
332 protected function getGroupName() {
333 return 'users';
334 }
335}
336
338class_alias( SpecialDeletedContributions::class, 'SpecialDeletedContributions' );
const NS_USER
Definition Defines.php:67
wfArrayInsertAfter(array $array, array $insert, $after)
Insert an array into another array after the specified key.
static showLogExtract(&$out, $types=[], $page='', $user='', $param=[])
Show log extract.
This is the main service interface for converting single-line comments from various DB comment fields...
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition HTMLForm.php:206
Helper class to keep track of options when mixing links and form elements.
A class containing constants representing the names of configuration variables.
const QueryPageDefaultLimit
Name constant for the QueryPageDefaultLimit setting, for use with Config::get()
A service class for checking permissions To obtain an instance, use MediaWikiServices::getInstance()-...
static getUserLinks(SpecialPage $sp, User $target, PermissionManager $permissionManager=null, HookRunner $hookRunner=null)
Links to different places.
Parent class for all special pages.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getSkin()
Shortcut to get the skin being used for this instance.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
checkPermissions()
Checks if userCanExecute, and if not throws a PermissionsError.
getConfig()
Shortcut to get main config object.
getContext()
Gets the context this SpecialPage is executed in.
getRequest()
Get the WebRequest being used for this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
getLanguage()
Shortcut to get user's language.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages By default the message key is the canonical name of...
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Implements Special:DeletedContributions to display archived revisions.
__construct(PermissionManager $permissionManager, IConnectionProvider $dbProvider, RevisionFactory $revisionFactory, NamespaceInfo $namespaceInfo, UserFactory $userFactory, UserNameUtils $userNameUtils, UserNamePrefixSearch $userNamePrefixSearch, CommentFormatter $commentFormatter, LinkBatchFactory $linkBatchFactory, DatabaseBlockStore $blockStore)
execute( $par)
Special page "deleted user contributions".
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
Creates User objects.
Handles searching prefixes of user names.
UserNameUtils service.
internal since 1.36
Definition User.php:93
Represents a block that may prevent users from performing specific operations.
Definition Block.php:45
Service for constructing RevisionRecord objects.
Shared interface for rigor levels when dealing with User methods.
Provide primary and replica IDatabase connections.