MediaWiki  1.34.0
Action.php
Go to the documentation of this file.
1 <?php
23 
39 abstract class Action implements MessageLocalizer {
40 
46  protected $page;
47 
53  protected $context;
54 
60  protected $fields;
61 
69  final private static function getClass( $action, array $overrides ) {
70  global $wgActions;
71  $action = strtolower( $action );
72 
73  if ( !isset( $wgActions[$action] ) ) {
74  return null;
75  }
76 
77  if ( $wgActions[$action] === false ) {
78  return false;
79  } elseif ( $wgActions[$action] === true && isset( $overrides[$action] ) ) {
80  return $overrides[$action];
81  } elseif ( $wgActions[$action] === true ) {
82  return ucfirst( $action ) . 'Action';
83  } else {
84  return $wgActions[$action];
85  }
86  }
87 
97  final public static function factory( $action, Page $page, IContextSource $context = null ) {
98  $classOrCallable = self::getClass( $action, $page->getActionOverrides() );
99 
100  if ( is_string( $classOrCallable ) ) {
101  if ( !class_exists( $classOrCallable ) ) {
102  return false;
103  }
104  return new $classOrCallable( $page, $context );
105  }
106 
107  if ( is_callable( $classOrCallable ) ) {
108  return $classOrCallable( $page, $context );
109  }
110 
111  return $classOrCallable;
112  }
113 
123  final public static function getActionName( IContextSource $context ) {
124  global $wgActions;
125 
126  $request = $context->getRequest();
127  $actionName = $request->getVal( 'action', 'view' );
128 
129  // Check for disabled actions
130  if ( isset( $wgActions[$actionName] ) && $wgActions[$actionName] === false ) {
131  $actionName = 'nosuchaction';
132  }
133 
134  // Workaround for T22966: inability of IE to provide an action dependent
135  // on which submit button is clicked.
136  if ( $actionName === 'historysubmit' ) {
137  if ( $request->getBool( 'revisiondelete' ) ) {
138  $actionName = 'revisiondelete';
139  } elseif ( $request->getBool( 'editchangetags' ) ) {
140  $actionName = 'editchangetags';
141  } else {
142  $actionName = 'view';
143  }
144  } elseif ( $actionName === 'editredlink' ) {
145  $actionName = 'edit';
146  }
147 
148  // Trying to get a WikiPage for NS_SPECIAL etc. will result
149  // in WikiPage::factory throwing "Invalid or virtual namespace -1 given."
150  // For SpecialPages et al, default to action=view.
151  if ( !$context->canUseWikiPage() ) {
152  return 'view';
153  }
154 
155  $action = self::factory( $actionName, $context->getWikiPage(), $context );
156  if ( $action instanceof Action ) {
157  return $action->getName();
158  }
159 
160  return 'nosuchaction';
161  }
162 
170  final public static function exists( $name ) {
171  return self::getClass( $name, [] ) !== null;
172  }
173 
179  final public function getContext() {
180  if ( $this->context instanceof IContextSource ) {
181  return $this->context;
182  } elseif ( $this->page instanceof Article ) {
183  // NOTE: $this->page can be a WikiPage, which does not have a context.
184  wfDebug( __METHOD__ . ": no context known, falling back to Article's context.\n" );
185  return $this->page->getContext();
186  }
187 
188  wfWarn( __METHOD__ . ': no context known, falling back to RequestContext::getMain().' );
189  return RequestContext::getMain();
190  }
191 
198  final public function getRequest() {
199  return $this->getContext()->getRequest();
200  }
201 
208  final public function getOutput() {
209  return $this->getContext()->getOutput();
210  }
211 
218  final public function getUser() {
219  return $this->getContext()->getUser();
220  }
221 
228  final public function getSkin() {
229  return $this->getContext()->getSkin();
230  }
231 
237  final public function getLanguage() {
238  return $this->getContext()->getLanguage();
239  }
240 
247  final public function getTitle() {
248  return $this->page->getTitle();
249  }
250 
259  final public function msg( $key, ...$params ) {
260  return $this->getContext()->msg( $key, ...$params );
261  }
262 
269  public function __construct( Page $page, IContextSource $context = null ) {
270  if ( $context === null ) {
271  wfWarn( __METHOD__ . ' called without providing a Context object.' );
272  // NOTE: We could try to initialize $context using $page->getContext(),
273  // if $page is an Article. That however seems to not work seamlessly.
274  }
275 
276  $this->page = $page;
277  $this->context = $context;
278  }
279 
286  abstract public function getName();
287 
295  public function getRestriction() {
296  return null;
297  }
298 
308  protected function checkCanExecute( User $user ) {
309  $right = $this->getRestriction();
310  if ( $right !== null ) {
311  $errors = $this->getTitle()->getUserPermissionsErrors( $right, $user );
312  if ( count( $errors ) ) {
313  throw new PermissionsError( $right, $errors );
314  }
315  }
316 
317  // If the action requires an unblock, explicitly check the user's block.
318  if ( $this->requiresUnblock() && $user->isBlockedFrom( $this->getTitle() ) ) {
319  $block = $user->getBlock();
320  if ( $block ) {
321  throw new UserBlockedError( $block );
322  }
323 
324  throw new PermissionsError( $this->getName(), [ 'badaccess-group0' ] );
325  }
326 
327  // This should be checked at the end so that the user won't think the
328  // error is only temporary when he also don't have the rights to execute
329  // this action
330  if ( $this->requiresWrite() && wfReadOnly() ) {
331  throw new ReadOnlyError();
332  }
333  }
334 
341  public function requiresWrite() {
342  return true;
343  }
344 
351  public function requiresUnblock() {
352  return true;
353  }
354 
360  protected function setHeaders() {
361  $out = $this->getOutput();
362  $out->setRobotPolicy( 'noindex,nofollow' );
363  $out->setPageTitle( $this->getPageTitle() );
364  $out->setSubtitle( $this->getDescription() );
365  $out->setArticleRelated( true );
366  }
367 
373  protected function getPageTitle() {
374  return $this->getTitle()->getPrefixedText();
375  }
376 
383  protected function getDescription() {
384  return $this->msg( strtolower( $this->getName() ) )->escaped();
385  }
386 
395  public function addHelpLink( $to, $overrideBaseUrl = false ) {
396  $msg = wfMessage( MediaWikiServices::getInstance()->getContentLanguage()->lc(
397  self::getActionName( $this->getContext() )
398  ) . '-helppage' );
399 
400  if ( !$msg->isDisabled() ) {
401  $helpUrl = Skin::makeUrl( $msg->plain() );
402  $this->getOutput()->addHelpLink( $helpUrl, true );
403  } else {
404  $this->getOutput()->addHelpLink( $to, $overrideBaseUrl );
405  }
406  }
407 
416  abstract public function show();
417 
422  protected function useTransactionalTimeLimit() {
423  if ( $this->getRequest()->wasPosted() ) {
425  }
426  }
427 
433  public function doesWrites() {
434  return false;
435  }
436 }
ReadOnlyError
Show an error when the wiki is locked/read-only and the user tries to do something that requires writ...
Definition: ReadOnlyError.php:28
Action\getActionName
static getActionName(IContextSource $context)
Get the action that will be executed, not necessarily the one passed passed through the "action" requ...
Definition: Action.php:123
$wgActions
$wgActions
Array of allowed values for the "title=foo&action=<action>" parameter.
Definition: DefaultSettings.php:7973
Page
Interface for type hinting (accepts WikiPage, Article, ImagePage, CategoryPage)
Definition: Page.php:29
Action\__construct
__construct(Page $page, IContextSource $context=null)
Only public since 1.21.
Definition: Action.php:269
UserBlockedError
Show an error when the user tries to do something whilst blocked.
Definition: UserBlockedError.php:29
Action\getDescription
getDescription()
Returns the description that goes below the <h1> tag.
Definition: Action.php:383
Action\setHeaders
setHeaders()
Set output headers for noindexing etc.
Definition: Action.php:360
User\isBlockedFrom
isBlockedFrom( $title, $fromReplica=false)
Check if user is blocked from editing a particular article.
Definition: User.php:2084
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:117
Action\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: Action.php:198
Action\doesWrites
doesWrites()
Indicates whether this action may perform database writes.
Definition: Action.php:433
Action\getName
getName()
Return the name of the action this object responds to.
wfReadOnly
wfReadOnly()
Check whether the wiki is in read-only mode.
Definition: GlobalFunctions.php:1171
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1264
PermissionsError
Show an error when a user tries to do something they do not have the necessary permissions for.
Definition: PermissionsError.php:30
MessageLocalizer
Interface for localizing messages in MediaWiki.
Definition: MessageLocalizer.php:28
Action
Actions are things which can be done to pages (edit, delete, rollback, etc).
Definition: Action.php:39
Action\getContext
getContext()
Get the IContextSource in use here.
Definition: Action.php:179
wfTransactionalTimeLimit
wfTransactionalTimeLimit()
Set PHP's time limit to the larger of php.ini or $wgTransactionalTimeLimit.
Definition: GlobalFunctions.php:2796
Action\checkCanExecute
checkCanExecute(User $user)
Checks if the given user (identified by an object) can perform this action.
Definition: Action.php:308
User\getBlock
getBlock( $fromReplica=true)
Get the block affecting the user, or null if the user is not blocked.
Definition: User.php:2068
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:913
Action\getUser
getUser()
Shortcut to get the User being used for this instance.
Definition: Action.php:218
Action\$context
$context
IContextSource if specified; otherwise we'll use the Context from the Page.
Definition: Action.php:53
Action\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: Action.php:395
Action\getTitle
getTitle()
Shortcut to get the Title object from the page.
Definition: Action.php:247
Action\requiresUnblock
requiresUnblock()
Whether this action can still be executed by a blocked user.
Definition: Action.php:351
Action\show
show()
The main action entry point.
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:431
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:53
Skin\makeUrl
static makeUrl( $name, $urlaction='')
Definition: Skin.php:1217
Action\exists
static exists( $name)
Check if a given action is recognised, even if it's disabled.
Definition: Action.php:170
Action\getSkin
getSkin()
Shortcut to get the Skin being used for this instance.
Definition: Action.php:228
Action\$page
$page
Page on which we're performing the action.
Definition: Action.php:46
Action\getClass
static getClass( $action, array $overrides)
Get the Action subclass which should be used to handle this action, false if the action is disabled,...
Definition: Action.php:69
Action\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: Action.php:259
Action\getLanguage
getLanguage()
Shortcut to get the user Language being used for this instance.
Definition: Action.php:237
Action\requiresWrite
requiresWrite()
Whether this action requires the wiki not to be locked.
Definition: Action.php:341
Action\$fields
$fields
The fields used to create the HTMLForm.
Definition: Action.php:60
Action\getPageTitle
getPageTitle()
Returns the name that goes in the <h1> page title.
Definition: Action.php:373
Action\getRestriction
getRestriction()
Get the permission required to perform this action.
Definition: Action.php:295
Action\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: Action.php:208
Action\useTransactionalTimeLimit
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
Definition: Action.php:422
wfWarn
wfWarn( $msg, $callerOffset=1, $level=E_USER_NOTICE)
Send a warning either to the debug log or in a PHP error depending on $wgDevelopmentWarnings.
Definition: GlobalFunctions.php:1065
Article
Class for viewing MediaWiki article and history.
Definition: Article.php:38
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:51
Action\factory
static factory( $action, Page $page, IContextSource $context=null)
Get an appropriate Action subclass for the given action.
Definition: Action.php:97