MediaWiki master
SpecialDeletedContributions.php
Go to the documentation of this file.
1<?php
24namespace MediaWiki\Specials;
25
44use Wikimedia\IPUtils;
46
53 protected $mOpts;
54
55 private PermissionManager $permissionManager;
56 private IConnectionProvider $dbProvider;
57 private RevisionFactory $revisionFactory;
58 private NamespaceInfo $namespaceInfo;
59 private UserFactory $userFactory;
60 private UserNameUtils $userNameUtils;
61 private UserNamePrefixSearch $userNamePrefixSearch;
62 private CommentFormatter $commentFormatter;
63 private LinkBatchFactory $linkBatchFactory;
64 private DatabaseBlockStore $blockStore;
65
78 public function __construct(
79 PermissionManager $permissionManager,
80 IConnectionProvider $dbProvider,
81 RevisionFactory $revisionFactory,
82 NamespaceInfo $namespaceInfo,
83 UserFactory $userFactory,
84 UserNameUtils $userNameUtils,
85 UserNamePrefixSearch $userNamePrefixSearch,
86 CommentFormatter $commentFormatter,
87 LinkBatchFactory $linkBatchFactory,
88 DatabaseBlockStore $blockStore
89 ) {
90 parent::__construct( 'DeletedContributions', 'deletedhistory' );
91 $this->permissionManager = $permissionManager;
92 $this->dbProvider = $dbProvider;
93 $this->revisionFactory = $revisionFactory;
94 $this->namespaceInfo = $namespaceInfo;
95 $this->userFactory = $userFactory;
96 $this->userNameUtils = $userNameUtils;
97 $this->userNamePrefixSearch = $userNamePrefixSearch;
98 $this->commentFormatter = $commentFormatter;
99 $this->linkBatchFactory = $linkBatchFactory;
100 $this->blockStore = $blockStore;
101 }
102
109 public function execute( $par ) {
110 $this->setHeaders();
111 $this->outputHeader();
112 $this->checkPermissions();
113 $out = $this->getOutput();
114 $out->addModuleStyles( [
115 'mediawiki.interface.helpers.styles',
116 'mediawiki.special.changeslist',
117 ] );
118 $this->addHelpLink( 'Help:User contributions' );
119
120 $opts = new FormOptions();
121
122 $opts->add( 'target', '' );
123 $opts->add( 'namespace', '' );
124 $opts->add( 'limit', 20 );
125
126 $opts->fetchValuesFromRequest( $this->getRequest() );
127 $opts->validateIntBounds( 'limit', 0,
129
130 if ( $par !== null ) {
131 // Beautify the username
132 $par = $this->userNameUtils->getCanonical( $par, UserRigorOptions::RIGOR_NONE );
133 $opts->setValue( 'target', (string)$par );
134 }
135
136 $ns = $opts->getValue( 'namespace' );
137 if ( $ns !== null && $ns !== '' ) {
138 $opts->setValue( 'namespace', intval( $ns ) );
139 }
140
141 $this->mOpts = $opts;
142
143 $target = trim( $opts->getValue( 'target' ) );
144 if ( !strlen( $target ) ) {
145 $this->getForm();
146
147 return;
148 }
149
150 $userObj = $this->userFactory->newFromName( $target, UserRigorOptions::RIGOR_NONE );
151 if ( !$userObj ) {
152 $this->getForm();
153
154 return;
155 }
156 // Only set valid local user as the relevant user (T344886)
157 // Uses the same condition as the SpecialContributions class did
158 if ( !IPUtils::isValidRange( $target ) &&
159 ( $this->userNameUtils->isIP( $target ) || $userObj->isRegistered() )
160 ) {
161 $this->getSkin()->setRelevantUser( $userObj );
162 }
163
164 $target = $userObj->getName();
165
166 $out->addSubtitle( $this->getSubTitle( $userObj ) );
167 $out->setPageTitleMsg( $this->msg( 'deletedcontributions-title' )->plaintextParams( $target ) );
168
169 $this->getForm();
170
171 $pager = new DeletedContribsPager(
172 $this->getContext(),
173 $this->getHookContainer(),
174 $this->getLinkRenderer(),
175 $this->dbProvider,
176 $this->revisionFactory,
177 $this->commentFormatter,
178 $this->linkBatchFactory,
179 $target,
180 $opts->getValue( 'namespace' )
181 );
182 if ( !$pager->getNumRows() ) {
183 $out->addWikiMsg( 'nocontribs' );
184
185 return;
186 }
187
188 # Show a message about replica DB lag, if applicable
189 $lag = $pager->getDatabase()->getSessionLagStatus()['lag'];
190 if ( $lag > 0 ) {
191 $out->showLagWarning( $lag );
192 }
193
194 $out->addHTML(
195 '<p>' . $pager->getNavigationBar() . '</p>' .
196 $pager->getBody() .
197 '<p>' . $pager->getNavigationBar() . '</p>' );
198
199 # If there were contributions, and it was a valid user or IP, show
200 # the appropriate "footer" message - WHOIS tools, etc.
201 $message = IPUtils::isIPAddress( $target ) ?
202 'sp-contributions-footer-anon' :
203 'sp-contributions-footer';
204
205 if ( !$this->msg( $message )->isDisabled() ) {
206 $out->wrapWikiMsg(
207 "<div class='mw-contributions-footer'>\n$1\n</div>",
208 [ $message, $target ]
209 );
210 }
211 }
212
218 private function getSubTitle( $userObj ) {
219 $linkRenderer = $this->getLinkRenderer();
220 if ( $userObj->isAnon() ) {
221 $user = htmlspecialchars( $userObj->getName() );
222 } else {
223 $user = $linkRenderer->makeLink( $userObj->getUserPage(), $userObj->getName() );
224 }
225 $links = '';
226 $nt = $userObj->getUserPage();
227 $talk = $nt->getTalkPage();
228 if ( $talk ) {
230 $this,
231 $userObj,
232 $this->permissionManager,
233 $this->getHookRunner()
234 );
235
236 $contributionsLink = $linkRenderer->makeKnownLink(
237 SpecialPage::getTitleFor( 'Contributions', $nt->getDBkey() ),
238 $this->msg( 'sp-deletedcontributions-contribs' )->text()
239 );
240 if ( isset( $tools['deletedcontribs'] ) ) {
241 // Swap out the deletedcontribs link for our contribs one
242 $tools = wfArrayInsertAfter(
243 $tools, [ 'contribs' => $contributionsLink ], 'deletedcontribs' );
244 unset( $tools['deletedcontribs'] );
245 } else {
246 $tools['contribs'] = $contributionsLink;
247 }
248
249 $links = $this->getLanguage()->pipeList( $tools );
250
251 // Show a note if the user is blocked and display the last block log entry.
252 $block = $this->blockStore->newFromTarget( $userObj, $userObj );
253 if ( $block !== null && $block->getType() != Block::TYPE_AUTO ) {
254 if ( $block->getType() == Block::TYPE_RANGE ) {
255 $nt = $this->namespaceInfo->getCanonicalName( NS_USER )
256 . ':' . $block->getTargetName();
257 }
258
259 // LogEventsList::showLogExtract() wants the first parameter by ref
260 $out = $this->getOutput();
262 $out,
263 'block',
264 $nt,
265 '',
266 [
267 'lim' => 1,
268 'showIfEmpty' => false,
269 'msgKey' => [
270 'sp-contributions-blocked-notice',
271 $userObj->getName() # Support GENDER in 'sp-contributions-blocked-notice'
272 ],
273 'offset' => '' # don't use $this->getRequest() parameter offset
274 ]
275 );
276 }
277 }
278
279 return $this->msg( 'contribsub2' )->rawParams( $user, $links )->params( $userObj->getName() );
280 }
281
285 private function getForm() {
286 $opts = $this->mOpts;
287
288 $formDescriptor = [
289 'target' => [
290 'type' => 'user',
291 'name' => 'target',
292 'label-message' => 'sp-contributions-username',
293 'default' => $opts->getValue( 'target' ),
294 'ipallowed' => true,
295 ],
296
297 'namespace' => [
298 'type' => 'namespaceselect',
299 'name' => 'namespace',
300 'label-message' => 'namespace',
301 'all' => '',
302 ],
303 ];
304
305 HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
306 ->setWrapperLegendMsg( 'sp-contributions-search' )
307 ->setSubmitTextMsg( 'sp-contributions-submit' )
308 // prevent setting subpage and 'target' parameter at the same time
309 ->setTitle( $this->getPageTitle() )
310 ->setMethod( 'get' )
311 ->prepareForm()
312 ->displayForm( false );
313 }
314
323 public function prefixSearchSubpages( $search, $limit, $offset ) {
324 $search = $this->userNameUtils->getCanonical( $search );
325 if ( !$search ) {
326 // No prefix suggestion for invalid user
327 return [];
328 }
329 // Autocomplete subpage as user list - public to allow caching
330 return $this->userNamePrefixSearch
331 ->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
332 }
333
334 protected function getGroupName() {
335 return 'users';
336 }
337}
338
340class_alias( SpecialDeletedContributions::class, 'SpecialDeletedContributions' );
const NS_USER
Definition Defines.php:66
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()-...
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 Per default the message key is the canonical name o...
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
static getUserLinks(SpecialPage $sp, User $target, PermissionManager $permissionManager=null, HookRunner $hookRunner=null)
Links to different places.
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.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...