MediaWiki  master
SpecialDeletedContributions.php
Go to the documentation of this file.
1 <?php
32 use Wikimedia\IPUtils;
34 
41  protected $mOpts;
42 
45 
47  private $loadBalancer;
48 
50  private $commentStore;
51 
54 
56  private $namespaceInfo;
57 
59  private $userFactory;
60 
62  private $userNameUtils;
63 
66 
77  public function __construct(
86  ) {
87  parent::__construct( 'DeletedContributions', 'deletedhistory' );
88  $this->permissionManager = $permissionManager;
89  $this->loadBalancer = $loadBalancer;
90  $this->commentStore = $commentStore;
91  $this->revisionFactory = $revisionFactory;
92  $this->namespaceInfo = $namespaceInfo;
93  $this->userFactory = $userFactory;
94  $this->userNameUtils = $userNameUtils;
95  $this->userNamePrefixSearch = $userNamePrefixSearch;
96  }
97 
104  public function execute( $par ) {
105  $this->setHeaders();
106  $this->outputHeader();
107  $this->checkPermissions();
108  $out = $this->getOutput();
109  $out->addModuleStyles( [
110  'mediawiki.interface.helpers.styles',
111  'mediawiki.special.changeslist',
112  ] );
113  $this->addHelpLink( 'Help:User contributions' );
114 
115  $opts = new FormOptions();
116 
117  $opts->add( 'target', '' );
118  $opts->add( 'namespace', '' );
119  $opts->add( 'limit', 20 );
120 
121  $opts->fetchValuesFromRequest( $this->getRequest() );
122  $opts->validateIntBounds( 'limit', 0,
123  $this->getConfig()->get( MainConfigNames::QueryPageDefaultLimit ) );
124 
125  if ( $par !== null ) {
126  // Beautify the username
127  $par = $this->userNameUtils->getCanonical( $par, UserRigorOptions::RIGOR_NONE );
128  $opts->setValue( 'target', (string)$par );
129  }
130 
131  $ns = $opts->getValue( 'namespace' );
132  if ( $ns !== null && $ns !== '' ) {
133  $opts->setValue( 'namespace', intval( $ns ) );
134  }
135 
136  $this->mOpts = $opts;
137 
138  $target = trim( $opts->getValue( 'target' ) );
139  if ( !strlen( $target ) ) {
140  $this->getForm();
141 
142  return;
143  }
144 
145  $userObj = $this->userFactory->newFromName( $target, UserRigorOptions::RIGOR_NONE );
146  if ( !$userObj ) {
147  $this->getForm();
148 
149  return;
150  }
151  $this->getSkin()->setRelevantUser( $userObj );
152 
153  $target = $userObj->getName();
154 
155  $out->addSubtitle( $this->getSubTitle( $userObj ) );
156  $out->setPageTitle( $this->msg( 'deletedcontributions-title', $target ) );
157 
158  $this->getForm();
159 
160  $pager = new DeletedContribsPager(
161  $this->getContext(),
162  $this->commentStore,
163  $this->getHookContainer(),
164  $this->getLinkRenderer(),
165  $this->loadBalancer,
166  $this->revisionFactory,
167  $target,
168  $opts->getValue( 'namespace' )
169  );
170  if ( !$pager->getNumRows() ) {
171  $out->addWikiMsg( 'nocontribs' );
172 
173  return;
174  }
175 
176  # Show a message about replica DB lag, if applicable
177  $lag = $pager->getDatabase()->getSessionLagStatus()['lag'];
178  if ( $lag > 0 ) {
179  $out->showLagWarning( $lag );
180  }
181 
182  $out->addHTML(
183  '<p>' . $pager->getNavigationBar() . '</p>' .
184  $pager->getBody() .
185  '<p>' . $pager->getNavigationBar() . '</p>' );
186 
187  # If there were contributions, and it was a valid user or IP, show
188  # the appropriate "footer" message - WHOIS tools, etc.
189  $message = IPUtils::isIPAddress( $target ) ?
190  'sp-contributions-footer-anon' :
191  'sp-contributions-footer';
192 
193  if ( !$this->msg( $message )->isDisabled() ) {
194  $out->wrapWikiMsg(
195  "<div class='mw-contributions-footer'>\n$1\n</div>",
196  [ $message, $target ]
197  );
198  }
199  }
200 
206  private function getSubTitle( $userObj ) {
207  $linkRenderer = $this->getLinkRenderer();
208  if ( $userObj->isAnon() ) {
209  $user = htmlspecialchars( $userObj->getName() );
210  } else {
211  $user = $linkRenderer->makeLink( $userObj->getUserPage(), $userObj->getName() );
212  }
213  $links = '';
214  $nt = $userObj->getUserPage();
215  $talk = $nt->getTalkPage();
216  if ( $talk ) {
218  $this,
219  $userObj,
220  $this->permissionManager,
221  $this->getHookRunner()
222  );
223 
224  $contributionsLink = $linkRenderer->makeKnownLink(
225  SpecialPage::getTitleFor( 'Contributions', $nt->getDBkey() ),
226  $this->msg( 'sp-deletedcontributions-contribs' )->text()
227  );
228  if ( isset( $tools['deletedcontribs'] ) ) {
229  // Swap out the deletedcontribs link for our contribs one
230  $tools = wfArrayInsertAfter(
231  $tools, [ 'contribs' => $contributionsLink ], 'deletedcontribs' );
232  unset( $tools['deletedcontribs'] );
233  } else {
234  $tools['contribs'] = $contributionsLink;
235  }
236 
237  $links = $this->getLanguage()->pipeList( $tools );
238 
239  // Show a note if the user is blocked and display the last block log entry.
240  $block = DatabaseBlock::newFromTarget( $userObj, $userObj );
241  if ( $block !== null && $block->getType() != DatabaseBlock::TYPE_AUTO ) {
242  if ( $block->getType() == DatabaseBlock::TYPE_RANGE ) {
243  $nt = $this->namespaceInfo->getCanonicalName( NS_USER )
244  . ':' . $block->getTargetName();
245  }
246 
247  // LogEventsList::showLogExtract() wants the first parameter by ref
248  $out = $this->getOutput();
250  $out,
251  'block',
252  $nt,
253  '',
254  [
255  'lim' => 1,
256  'showIfEmpty' => false,
257  'msgKey' => [
258  'sp-contributions-blocked-notice',
259  $userObj->getName() # Support GENDER in 'sp-contributions-blocked-notice'
260  ],
261  'offset' => '' # don't use $this->getRequest() parameter offset
262  ]
263  );
264  }
265  }
266 
267  return $this->msg( 'contribsub2' )->rawParams( $user, $links )->params( $userObj->getName() );
268  }
269 
273  private function getForm() {
274  $opts = $this->mOpts;
275 
276  $formDescriptor = [
277  'target' => [
278  'type' => 'user',
279  'name' => 'target',
280  'label-message' => 'sp-contributions-username',
281  'default' => $opts->getValue( 'target' ),
282  'ipallowed' => true,
283  ],
284 
285  'namespace' => [
286  'type' => 'namespaceselect',
287  'name' => 'namespace',
288  'label-message' => 'namespace',
289  'all' => '',
290  ],
291  ];
292 
293  HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
294  ->setWrapperLegendMsg( 'sp-contributions-search' )
295  ->setSubmitTextMsg( 'sp-contributions-submit' )
296  // prevent setting subpage and 'target' parameter at the same time
297  ->setTitle( $this->getPageTitle() )
298  ->setMethod( 'get' )
299  ->prepareForm()
300  ->displayForm( false );
301  }
302 
311  public function prefixSearchSubpages( $search, $limit, $offset ) {
312  $search = $this->userNameUtils->getCanonical( $search );
313  if ( !$search ) {
314  // No prefix suggestion for invalid user
315  return [];
316  }
317  // Autocomplete subpage as user list - public to allow caching
318  return $this->userNamePrefixSearch
319  ->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
320  }
321 
322  protected function getGroupName() {
323  return 'users';
324  }
325 }
const NS_USER
Definition: Defines.php:66
wfArrayInsertAfter(array $array, array $insert, $after)
Insert an array into another array after the specified key.
Handle database storage of comments such as edit summaries and log reasons.
Helper class to keep track of options when mixing links and form elements.
Definition: FormOptions.php:35
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...
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.
Definition: UserFactory.php:38
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.
getSubTitle( $userObj)
Generates the subheading with links.
execute( $par)
Special page "deleted user contributions".
__construct(PermissionManager $permissionManager, ILoadBalancer $loadBalancer, CommentStore $commentStore, RevisionFactory $revisionFactory, NamespaceInfo $namespaceInfo, UserFactory $userFactory, UserNameUtils $userNameUtils, UserNamePrefixSearch $userNamePrefixSearch)
getForm()
Generates the namespace selector form with hidden attributes.
Parent class for all special pages.
Definition: SpecialPage.php:44
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.
LinkRenderer null $linkRenderer
Definition: SpecialPage.php:81
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.
Database cluster connection, tracking, load balancing, and transaction manager interface.