MediaWiki  master
Action.php
Go to the documentation of this file.
1 <?php
25 
43 abstract class Action implements MessageLocalizer {
44 
53  protected $page;
54 
59  private $article;
60 
66  protected $context;
67 
73  protected $fields;
74 
82  final private static function getClass(
83  string $action,
84  array $overrides
85  ) {
86  global $wgActions;
87  $action = strtolower( $action );
88 
89  if ( !isset( $wgActions[$action] ) ) {
90  return null;
91  }
92 
93  if ( $wgActions[$action] === false ) {
94  return false;
95  } elseif ( $wgActions[$action] === true && isset( $overrides[$action] ) ) {
96  return $overrides[$action];
97  } elseif ( $wgActions[$action] === true ) {
98  return ucfirst( $action ) . 'Action';
99  } else {
100  return $wgActions[$action];
101  }
102  }
103 
115  final public static function factory(
116  ?string $action,
117  Page $article,
118  IContextSource $context = null
119  ) {
120  if ( !is_string( $action ) ) {
121  wfDeprecated( __METHOD__ . ' with null $action', '1.35' );
122  return null;
123  }
124  if ( !$article instanceof Article ) {
125  wfDeprecated(
126  __METHOD__ . ' with ' . get_class( $article ),
127  '1.35'
128  );
129  }
130  $classOrCallable = self::getClass( $action, $article->getActionOverrides() );
131  if ( is_string( $classOrCallable ) ) {
132  if ( !class_exists( $classOrCallable ) ) {
133  return false;
134  }
135  return new $classOrCallable( $article, $context );
136  }
137 
138  if ( is_callable( $classOrCallable ) ) {
139  return $classOrCallable( $article, $context );
140  }
141 
142  return $classOrCallable;
143  }
144 
154  final public static function getActionName( IContextSource $context ) {
155  global $wgActions;
156 
157  $request = $context->getRequest();
158  $actionName = $request->getVal( 'action', 'view' );
159 
160  // Check for disabled actions
161  if ( isset( $wgActions[$actionName] ) && $wgActions[$actionName] === false ) {
162  $actionName = 'nosuchaction';
163  }
164 
165  // Workaround for T22966: inability of IE to provide an action dependent
166  // on which submit button is clicked.
167  if ( $actionName === 'historysubmit' ) {
168  if ( $request->getBool( 'revisiondelete' ) ) {
169  $actionName = 'revisiondelete';
170  } elseif ( $request->getBool( 'editchangetags' ) ) {
171  $actionName = 'editchangetags';
172  } else {
173  $actionName = 'view';
174  }
175  } elseif ( $actionName === 'editredlink' ) {
176  $actionName = 'edit';
177  }
178 
179  // Trying to get a WikiPage for NS_SPECIAL etc. will result
180  // in WikiPage::factory throwing "Invalid or virtual namespace -1 given."
181  // For SpecialPages et al, default to action=view.
182  if ( !$context->canUseWikiPage() ) {
183  return 'view';
184  }
185 
186  $action = self::factory(
187  $actionName,
189  $context
190  );
191 
192  if ( $action instanceof Action ) {
193  return $action->getName();
194  }
195 
196  return 'nosuchaction';
197  }
198 
206  final public static function exists( string $name ) : bool {
207  return self::getClass( $name, [] ) !== null;
208  }
209 
215  final public function getContext() {
216  if ( $this->context instanceof IContextSource ) {
217  return $this->context;
218  }
219  wfDebug( __METHOD__ . ": no context known, falling back to Article's context." );
220  return $this->getArticle()->getContext();
221  }
222 
229  final public function getRequest() {
230  return $this->getContext()->getRequest();
231  }
232 
239  final public function getOutput() {
240  return $this->getContext()->getOutput();
241  }
242 
249  final public function getUser() {
250  return $this->getContext()->getUser();
251  }
252 
259  final public function getSkin() {
260  return $this->getContext()->getSkin();
261  }
262 
268  final public function getLanguage() {
269  return $this->getContext()->getLanguage();
270  }
271 
278  final public function getWikiPage() : WikiPage {
279  return $this->getArticle()->getPage();
280  }
281 
289  public function getArticle() {
290  return $this->article;
291  }
292 
299  final public function getTitle() {
300  return $this->getWikiPage()->getTitle();
301  }
302 
311  final public function msg( $key, ...$params ) {
312  return $this->getContext()->msg( $key, ...$params );
313  }
314 
319  protected function getHookContainer() {
320  return MediaWikiServices::getInstance()->getHookContainer();
321  }
322 
329  protected function getHookRunner() {
330  return new HookRunner( $this->getHookContainer() );
331  }
332 
342  public function __construct(
343  Page $page,
344  IContextSource $context = null
345  ) {
346  if ( $context === null ) {
347  wfWarn( __METHOD__ . ' called without providing a Context object.' );
348  }
349 
350  $this->page = $page;// @todo remove b/c
351  $this->article = self::convertPageToArticle( $page, $context, __METHOD__ );
352  $this->context = $context;
353  }
354 
355  private static function convertPageToArticle(
356  Page $page,
358  string $method
359  ) : Article {
360  if ( $page instanceof Article ) {
361  return $page;
362  }
363 
364  if ( !$page instanceof WikiPage ) {
365  throw new LogicException(
366  $method . ' called with unknown Page: ' . get_class( $page )
367  );
368  }
369 
370  wfDeprecated(
371  $method . ' with: ' . get_class( $page ),
372  '1.35'
373  );
374 
376  $page,
378  );
379  }
380 
387  abstract public function getName();
388 
397  public function getRestriction() {
398  return null;
399  }
400 
411  protected function checkCanExecute( User $user ) {
412  $right = $this->getRestriction();
413  if ( $right !== null ) {
414  $errors = MediaWikiServices::getInstance()->getPermissionManager()
415  ->getPermissionErrors( $right, $user, $this->getTitle() );
416  if ( count( $errors ) ) {
417  throw new PermissionsError( $right, $errors );
418  }
419  }
420 
421  // If the action requires an unblock, explicitly check the user's block.
422  if ( $this->requiresUnblock() && $user->isBlockedFrom( $this->getTitle() ) ) {
423  $block = $user->getBlock();
424  if ( $block ) {
425  throw new UserBlockedError(
426  $block,
427  $user,
428  $this->getLanguage(),
429  $this->getRequest()->getIP()
430  );
431  }
432 
433  throw new PermissionsError( $this->getName(), [ 'badaccess-group0' ] );
434  }
435 
436  // This should be checked at the end so that the user won't think the
437  // error is only temporary when he also don't have the rights to execute
438  // this action
439  if ( $this->requiresWrite() && wfReadOnly() ) {
440  throw new ReadOnlyError();
441  }
442  }
443 
451  public function requiresWrite() {
452  return true;
453  }
454 
462  public function requiresUnblock() {
463  return true;
464  }
465 
472  protected function setHeaders() {
473  $out = $this->getOutput();
474  $out->setRobotPolicy( 'noindex,nofollow' );
475  $out->setPageTitle( $this->getPageTitle() );
476  $out->setSubtitle( $this->getDescription() );
477  $out->setArticleRelated( true );
478  }
479 
486  protected function getPageTitle() {
487  return $this->getTitle()->getPrefixedText();
488  }
489 
497  protected function getDescription() {
498  return $this->msg( strtolower( $this->getName() ) )->escaped();
499  }
500 
509  public function addHelpLink( $to, $overrideBaseUrl = false ) {
510  $msg = wfMessage( MediaWikiServices::getInstance()->getContentLanguage()->lc(
511  self::getActionName( $this->getContext() )
512  ) . '-helppage' );
513 
514  if ( !$msg->isDisabled() ) {
515  $helpUrl = Skin::makeUrl( $msg->plain() );
516  $this->getOutput()->addHelpLink( $helpUrl, true );
517  } else {
518  $this->getOutput()->addHelpLink( $to, $overrideBaseUrl );
519  }
520  }
521 
530  abstract public function show();
531 
536  protected function useTransactionalTimeLimit() {
537  if ( $this->getRequest()->wasPosted() ) {
539  }
540  }
541 
548  public function doesWrites() {
549  return false;
550  }
551 }
ReadOnlyError
Show an error when the wiki is locked/read-only and the user tries to do something that requires writ...
Definition: ReadOnlyError.php:29
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:154
$wgActions
$wgActions
Array of allowed values for the "title=foo&action=<action>" parameter.
Definition: DefaultSettings.php:8406
Page
Interface for type hinting (accepts WikiPage, Article, ImagePage, CategoryPage)
Definition: Page.php:30
Action\__construct
__construct(Page $page, IContextSource $context=null)
Only public since 1.21.
Definition: Action.php:342
UserBlockedError
Show an error when the user tries to do something whilst blocked.
Definition: UserBlockedError.php:31
Action\getDescription
getDescription()
Returns the description that goes below the <h1> tag.
Definition: Action.php:497
Action\setHeaders
setHeaders()
Set output headers for noindexing etc.
Definition: Action.php:472
User\isBlockedFrom
isBlockedFrom( $title, $fromReplica=false)
Check if user is blocked from editing a particular article.
Definition: User.php:1811
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:154
Action\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: Action.php:229
Action\doesWrites
doesWrites()
Indicates whether this action may perform database writes.
Definition: Action.php:548
CategoryPage
Special handling for category description pages, showing pages, subcategories and file that belong to...
Definition: CategoryPage.php:30
WikiPage
Class representing a MediaWiki article and history.
Definition: WikiPage.php:52
Action\exists
static exists(string $name)
Check if a given action is recognised, even if it's disabled.
Definition: Action.php:206
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:1125
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1219
Action\getClass
static getClass(string $action, array $overrides)
Get the Action subclass which should be used to handle this action, false if the action is disabled,...
Definition: Action.php:82
ImagePage
Class for viewing MediaWiki file description pages.
Definition: ImagePage.php:33
PermissionsError
Show an error when a user tries to do something they do not have the necessary permissions for.
Definition: PermissionsError.php:31
Action\factory
static factory(?string $action, Page $article, IContextSource $context=null)
Get an appropriate Action subclass for the given action.
Definition: Action.php:115
MessageLocalizer
Interface for localizing messages in MediaWiki.
Definition: MessageLocalizer.php:29
Action
Actions are things which can be done to pages (edit, delete, rollback, etc).
Definition: Action.php:43
Action\getContext
getContext()
Get the IContextSource in use here.
Definition: Action.php:215
Article\newFromWikiPage
static newFromWikiPage(WikiPage $page, IContextSource $context)
Create an Article object of the appropriate class for the given page.
Definition: Article.php:226
IContextSource\canUseWikiPage
canUseWikiPage()
Check whether a WikiPage object can be get with getWikiPage().
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:1026
Action\getArticle
getArticle()
Get a Article object.
Definition: Action.php:289
wfTransactionalTimeLimit
wfTransactionalTimeLimit()
Set PHP's time limit to the larger of php.ini or $wgTransactionalTimeLimit.
Definition: GlobalFunctions.php:2642
IContextSource\getWikiPage
getWikiPage()
Get the WikiPage object.
Action\checkCanExecute
checkCanExecute(User $user)
Checks if the given user (identified by an object) can perform this action.
Definition: Action.php:411
Action\convertPageToArticle
static convertPageToArticle(Page $page, ?IContextSource $context, string $method)
Definition: Action.php:355
User\getBlock
getBlock( $fromReplica=true)
Get the block affecting the user, or null if the user is not blocked.
Definition: User.php:1795
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:909
Action\getWikiPage
getWikiPage()
Get a WikiPage object.
Definition: Action.php:278
Action\$article
Article $article
Definition: Action.php:59
Action\getUser
getUser()
Shortcut to get the User being used for this instance.
Definition: Action.php:249
Action\$context
IContextSource $context
IContextSource if specified; otherwise we'll use the Context from the Page.
Definition: Action.php:66
Action\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: Action.php:509
Action\getTitle
getTitle()
Shortcut to get the Title object from the page.
Definition: Action.php:299
Action\requiresUnblock
requiresUnblock()
Whether this action can still be executed by a blocked user.
Definition: Action.php:462
Action\show
show()
The main action entry point.
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:453
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:55
Action\getHookRunner
getHookRunner()
Definition: Action.php:329
Skin\makeUrl
static makeUrl( $name, $urlaction='')
Definition: Skin.php:1249
Action\getSkin
getSkin()
Shortcut to get the Skin being used for this instance.
Definition: Action.php:259
Action\$page
WikiPage Article ImagePage CategoryPage Page $page
Page on which we're performing the action.
Definition: Action.php:53
Action\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: Action.php:311
Action\getLanguage
getLanguage()
Shortcut to get the user Language being used for this instance.
Definition: Action.php:268
Action\requiresWrite
requiresWrite()
Whether this action requires the wiki not to be locked.
Definition: Action.php:451
Action\$fields
array $fields
The fields used to create the HTMLForm.
Definition: Action.php:73
Article\getActionOverrides
getActionOverrides()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2540
Action\getPageTitle
getPageTitle()
Returns the name that goes in the <h1> page title.
Definition: Action.php:486
Action\getRestriction
getRestriction()
Get the permission required to perform this action.
Definition: Action.php:397
Action\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: Action.php:239
IContextSource\getRequest
getRequest()
Action\useTransactionalTimeLimit
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
Definition: Action.php:536
MediaWiki\HookContainer\HookContainer
HookContainer class.
Definition: HookContainer.php:44
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:1073
MediaWiki\HookContainer\HookRunner
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Definition: HookRunner.php:570
Article
Class for viewing MediaWiki article and history.
Definition: Article.php:46
Action\getHookContainer
getHookContainer()
Definition: Action.php:319
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:55