MediaWiki REL1_40
SpecialDeletedContributions.php
Go to the documentation of this file.
1<?php
35use Wikimedia\IPUtils;
37
44 protected $mOpts;
45
47 private $permissionManager;
48
50 private $loadBalancer;
51
53 private $revisionFactory;
54
56 private $namespaceInfo;
57
59 private $userFactory;
60
62 private $userNameUtils;
63
65 private $userNamePrefixSearch;
66
68 private $commentFormatter;
69
71 private $linkBatchFactory;
72
84 public function __construct(
85 PermissionManager $permissionManager,
86 ILoadBalancer $loadBalancer,
87 RevisionFactory $revisionFactory,
88 NamespaceInfo $namespaceInfo,
89 UserFactory $userFactory,
90 UserNameUtils $userNameUtils,
91 UserNamePrefixSearch $userNamePrefixSearch,
92 CommentFormatter $commentFormatter,
93 LinkBatchFactory $linkBatchFactory
94 ) {
95 parent::__construct( 'DeletedContributions', 'deletedhistory' );
96 $this->permissionManager = $permissionManager;
97 $this->loadBalancer = $loadBalancer;
98 $this->revisionFactory = $revisionFactory;
99 $this->namespaceInfo = $namespaceInfo;
100 $this->userFactory = $userFactory;
101 $this->userNameUtils = $userNameUtils;
102 $this->userNamePrefixSearch = $userNamePrefixSearch;
103 $this->commentFormatter = $commentFormatter;
104 $this->linkBatchFactory = $linkBatchFactory;
105 }
106
113 public function execute( $par ) {
114 $this->setHeaders();
115 $this->outputHeader();
116 $this->checkPermissions();
117 $out = $this->getOutput();
118 $out->addModuleStyles( [
119 'mediawiki.interface.helpers.styles',
120 'mediawiki.special.changeslist',
121 ] );
122 $this->addHelpLink( 'Help:User contributions' );
123
124 $opts = new FormOptions();
125
126 $opts->add( 'target', '' );
127 $opts->add( 'namespace', '' );
128 $opts->add( 'limit', 20 );
129
130 $opts->fetchValuesFromRequest( $this->getRequest() );
131 $opts->validateIntBounds( 'limit', 0,
132 $this->getConfig()->get( MainConfigNames::QueryPageDefaultLimit ) );
133
134 if ( $par !== null ) {
135 // Beautify the username
136 $par = $this->userNameUtils->getCanonical( $par, UserRigorOptions::RIGOR_NONE );
137 $opts->setValue( 'target', (string)$par );
138 }
139
140 $ns = $opts->getValue( 'namespace' );
141 if ( $ns !== null && $ns !== '' ) {
142 $opts->setValue( 'namespace', intval( $ns ) );
143 }
144
145 $this->mOpts = $opts;
146
147 $target = trim( $opts->getValue( 'target' ) );
148 if ( !strlen( $target ) ) {
149 $this->getForm();
150
151 return;
152 }
153
154 $userObj = $this->userFactory->newFromName( $target, UserRigorOptions::RIGOR_NONE );
155 if ( !$userObj ) {
156 $this->getForm();
157
158 return;
159 }
160 $this->getSkin()->setRelevantUser( $userObj );
161
162 $target = $userObj->getName();
163
164 $out->addSubtitle( $this->getSubTitle( $userObj ) );
165 $out->setPageTitle( $this->msg( 'deletedcontributions-title', $target ) );
166
167 $this->getForm();
168
169 $pager = new DeletedContribsPager(
170 $this->getContext(),
171 $this->getHookContainer(),
172 $this->getLinkRenderer(),
173 $this->loadBalancer,
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 = DatabaseBlock::newFromTarget( $userObj, $userObj );
251 if ( $block !== null && $block->getType() != DatabaseBlock::TYPE_AUTO ) {
252 if ( $block->getType() == DatabaseBlock::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}
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.
A DatabaseBlock (unlike a SystemBlock) is stored in the database, may give rise to autoblocks and may...
This is the main service interface for converting single-line comments from various DB comment fields...
Helper class to keep track of options when mixing links and form elements.
A class containing constants representing the names of configuration variables.
A service class for checking permissions To obtain an instance, use MediaWikiServices::getInstance()-...
Creates User objects.
Handles searching prefixes of user names.
UserNameUtils service.
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
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, ILoadBalancer $loadBalancer, RevisionFactory $revisionFactory, NamespaceInfo $namespaceInfo, UserFactory $userFactory, UserNameUtils $userNameUtils, UserNamePrefixSearch $userNamePrefixSearch, CommentFormatter $commentFormatter, LinkBatchFactory $linkBatchFactory)
execute( $par)
Special page "deleted user contributions".
Parent class for all special pages.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getOutput()
Get the OutputPage being used for this instance.
getSkin()
Shortcut to get the skin being used for this instance.
checkPermissions()
Checks if userCanExecute, and if not throws a PermissionsError.
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,...
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getConfig()
Shortcut to get main config object.
getRequest()
Get the WebRequest being used for this instance.
getLanguage()
Shortcut to get user's language.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Service for constructing RevisionRecord objects.
Shared interface for rigor levels when dealing with User methods.
This class is a delegate to ILBFactory for a given database cluster.