MediaWiki  master
SpecialUnblock.php
Go to the documentation of this file.
1 <?php
30 
36 class SpecialUnblock extends SpecialPage {
37 
39  protected $target;
40 
42  protected $type;
43 
44  protected $block;
45 
47  private $unblockUserFactory;
48 
50  private $blockUtils;
51 
53  private $userNameUtils;
54 
56  private $userNamePrefixSearch;
57 
64  public function __construct(
65  UnblockUserFactory $unblockUserFactory,
66  BlockUtils $blockUtils,
67  UserNameUtils $userNameUtils,
68  UserNamePrefixSearch $userNamePrefixSearch
69  ) {
70  parent::__construct( 'Unblock', 'block' );
71  $this->unblockUserFactory = $unblockUserFactory;
72  $this->blockUtils = $blockUtils;
73  $this->userNameUtils = $userNameUtils;
74  $this->userNamePrefixSearch = $userNamePrefixSearch;
75  }
76 
77  public function doesWrites() {
78  return true;
79  }
80 
81  public function execute( $par ) {
82  $this->checkPermissions();
83  $this->checkReadOnly();
84 
85  [ $this->target, $this->type ] = $this->getTargetAndType( $par, $this->getRequest() );
86  $this->block = DatabaseBlock::newFromTarget( $this->target );
87  if ( $this->target instanceof UserIdentity ) {
88  # Set the 'relevant user' in the skin, so it displays links like Contributions,
89  # User logs, UserRights, etc.
90  $this->getSkin()->setRelevantUser( $this->target );
91  }
92 
93  $this->setHeaders();
94  $this->outputHeader();
95  $this->addHelpLink( 'Help:Blocking users' );
96 
97  $out = $this->getOutput();
98  $out->setPageTitle( $this->msg( 'unblockip' ) );
99  $out->addModules( [ 'mediawiki.userSuggest' ] );
100 
101  $form = HTMLForm::factory( 'ooui', $this->getFields(), $this->getContext() )
102  ->setWrapperLegendMsg( 'unblockip' )
103  ->setSubmitCallback( function ( array $data, HTMLForm $form ) {
104  return $this->unblockUserFactory->newUnblockUser(
105  $data['Target'],
106  $form->getContext()->getAuthority(),
107  $data['Reason'],
108  $data['Tags'] ?? []
109  )->unblock();
110  } )
111  ->setSubmitTextMsg( 'ipusubmit' )
112  ->addPreText( $this->msg( 'unblockiptext' )->parseAsBlock() );
113 
114  if ( $form->show() ) {
115  switch ( $this->type ) {
116  case DatabaseBlock::TYPE_IP:
117  // @phan-suppress-next-line PhanTypeMismatchArgumentNullable target is set when type is set
118  $out->addWikiMsg( 'unblocked-ip', wfEscapeWikiText( $this->target ) );
119  break;
120  case DatabaseBlock::TYPE_USER:
121  // @phan-suppress-next-line PhanTypeMismatchArgumentNullable target is set when type is set
122  $out->addWikiMsg( 'unblocked', wfEscapeWikiText( $this->target ) );
123  break;
124  case DatabaseBlock::TYPE_RANGE:
125  // @phan-suppress-next-line PhanTypeMismatchArgumentNullable target is set when type is set
126  $out->addWikiMsg( 'unblocked-range', wfEscapeWikiText( $this->target ) );
127  break;
128  case DatabaseBlock::TYPE_ID:
129  case DatabaseBlock::TYPE_AUTO:
130  // @phan-suppress-next-line PhanTypeMismatchArgumentNullable target is set when type is set
131  $out->addWikiMsg( 'unblocked-id', wfEscapeWikiText( $this->target ) );
132  break;
133  }
134  }
135  }
136 
147  private function getTargetAndType( ?string $par, WebRequest $request ) {
148  $possibleTargets = [
149  $request->getVal( 'wpTarget', null ),
150  $par,
151  $request->getVal( 'ip', null ),
152  // B/C @since 1.18
153  $request->getVal( 'wpBlockAddress', null ),
154  ];
155  foreach ( $possibleTargets as $possibleTarget ) {
156  $targetAndType = $this->blockUtils->parseBlockTarget( $possibleTarget );
157  // If type is not null then target is valid
158  if ( $targetAndType[ 1 ] !== null ) {
159  break;
160  }
161  }
162  return $targetAndType;
163  }
164 
165  protected function getFields() {
166  $fields = [
167  'Target' => [
168  'type' => 'text',
169  'label-message' => 'ipaddressorusername',
170  'autofocus' => true,
171  'size' => '45',
172  'required' => true,
173  'cssclass' => 'mw-autocomplete-user', // used by mediawiki.userSuggest
174  ],
175  'Name' => [
176  'type' => 'info',
177  'label-message' => 'ipaddressorusername',
178  ],
179  'Reason' => [
180  'type' => 'text',
181  'label-message' => 'ipbreason',
182  ]
183  ];
184 
185  if ( $this->block instanceof DatabaseBlock ) {
186  $type = $this->block->getType();
187  $targetName = $this->block->getTargetName();
188 
189  # Autoblocks are logged as "autoblock #123 because the IP was recently used by
190  # User:Foo, and we've just got any block, auto or not, that applies to a target
191  # the user has specified. Someone could be fishing to connect IPs to autoblocks,
192  # so don't show any distinction between unblocked IPs and autoblocked IPs
193  if ( $type == DatabaseBlock::TYPE_AUTO && $this->type == DatabaseBlock::TYPE_IP ) {
194  $fields['Target']['default'] = $this->target;
195  unset( $fields['Name'] );
196  } else {
197  $fields['Target']['default'] = $targetName;
198  $fields['Target']['type'] = 'hidden';
199  switch ( $type ) {
200  case DatabaseBlock::TYPE_IP:
201  $fields['Name']['default'] = $this->getLinkRenderer()->makeKnownLink(
202  $this->getSpecialPageFactory()->getTitleForAlias( 'Contributions/' . $targetName ),
203  $targetName
204  );
205  $fields['Name']['raw'] = true;
206  break;
207  case DatabaseBlock::TYPE_USER:
208  $fields['Name']['default'] = $this->getLinkRenderer()->makeLink(
209  new TitleValue( NS_USER, $targetName ),
210  $targetName
211  );
212  $fields['Name']['raw'] = true;
213  break;
214 
215  case DatabaseBlock::TYPE_RANGE:
216  $fields['Name']['default'] = $targetName;
217  break;
218 
219  case DatabaseBlock::TYPE_AUTO:
220  $fields['Name']['default'] = $this->block->getRedactedName();
221  $fields['Name']['raw'] = true;
222  # Don't expose the real target of the autoblock
223  $fields['Target']['default'] = "#{$this->target}";
224  break;
225  }
226  // target is hidden, so the reason is the first element
227  $fields['Target']['autofocus'] = false;
228  $fields['Reason']['autofocus'] = true;
229  }
230  } else {
231  $fields['Target']['default'] = $this->target;
232  unset( $fields['Name'] );
233  }
234 
235  return $fields;
236  }
237 
246  public function prefixSearchSubpages( $search, $limit, $offset ) {
247  $search = $this->userNameUtils->getCanonical( $search );
248  if ( !$search ) {
249  // No prefix suggestion for invalid user
250  return [];
251  }
252  // Autocomplete subpage as user list - public to allow caching
253  return $this->userNamePrefixSearch
254  ->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
255  }
256 
257  protected function getGroupName() {
258  return 'users';
259  }
260 }
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
getContext()
Get the base IContextSource object.
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition: HTMLForm.php:150
show()
The here's-one-I-made-earlier option: do the submission if posted, or display the form with or withou...
Definition: HTMLForm.php:633
static factory( $displayFormat, $descriptor, IContextSource $context, $messagePrefix='')
Construct a HTMLForm object for given display type.
Definition: HTMLForm.php:349
Backend class for blocking utils.
Definition: BlockUtils.php:46
A DatabaseBlock (unlike a SystemBlock) is stored in the database, may give rise to autoblocks and may...
Handles searching prefixes of user names.
UserNameUtils service.
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.
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getRequest()
Get the WebRequest being used for this instance.
checkReadOnly()
If the wiki is currently in readonly mode, throws a ReadOnlyError.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
A special page for unblocking users.
UserIdentity string null $target
doesWrites()
Indicates whether this special page may perform database writes.
execute( $par)
Default execute method Checks user permissions.
__construct(UnblockUserFactory $unblockUserFactory, BlockUtils $blockUtils, UserNameUtils $userNameUtils, UserNamePrefixSearch $userNamePrefixSearch)
int null $type
DatabaseBlock::TYPE_ constant.
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Definition: WebRequest.php:47
getVal( $name, $default=null)
Fetch a text string and partially normalized it.
Definition: WebRequest.php:516
Interface for objects representing user identity.