MediaWiki  master
Action.php
Go to the documentation of this file.
1 <?php
25 
41 abstract class Action implements MessageLocalizer {
42 
51  protected $page;
52 
57  private $article;
58 
64  protected $context;
65 
71  protected $fields;
72 
80  final private static function getClass(
81  string $action,
82  array $overrides
83  ) {
84  global $wgActions;
85  $action = strtolower( $action );
86 
87  if ( !isset( $wgActions[$action] ) ) {
88  return null;
89  }
90 
91  if ( $wgActions[$action] === false ) {
92  return false;
93  } elseif ( $wgActions[$action] === true && isset( $overrides[$action] ) ) {
94  return $overrides[$action];
95  } elseif ( $wgActions[$action] === true ) {
96  return ucfirst( $action ) . 'Action';
97  } else {
98  return $wgActions[$action];
99  }
100  }
101 
113  final public static function factory(
114  ?string $action,
115  Page $article,
116  IContextSource $context = null
117  ) {
118  if ( !is_string( $action ) ) {
119  wfDeprecated( __METHOD__ . ' with null $action', '1.35' );
120  return null;
121  }
122  if ( !$article instanceof Article ) {
123  wfDeprecated(
124  __METHOD__ . ' with ' . get_class( $article ),
125  '1.35'
126  );
127  }
128  $classOrCallable = self::getClass( $action, $article->getActionOverrides() );
129  if ( is_string( $classOrCallable ) ) {
130  if ( !class_exists( $classOrCallable ) ) {
131  return false;
132  }
133  return new $classOrCallable( $article, $context );
134  }
135 
136  if ( is_callable( $classOrCallable ) ) {
137  return $classOrCallable( $article, $context );
138  }
139 
140  return $classOrCallable;
141  }
142 
152  final public static function getActionName( IContextSource $context ) {
153  global $wgActions;
154 
155  $request = $context->getRequest();
156  $actionName = $request->getVal( 'action', 'view' );
157 
158  // Check for disabled actions
159  if ( isset( $wgActions[$actionName] ) && $wgActions[$actionName] === false ) {
160  $actionName = 'nosuchaction';
161  }
162 
163  // Workaround for T22966: inability of IE to provide an action dependent
164  // on which submit button is clicked.
165  if ( $actionName === 'historysubmit' ) {
166  if ( $request->getBool( 'revisiondelete' ) ) {
167  $actionName = 'revisiondelete';
168  } elseif ( $request->getBool( 'editchangetags' ) ) {
169  $actionName = 'editchangetags';
170  } else {
171  $actionName = 'view';
172  }
173  } elseif ( $actionName === 'editredlink' ) {
174  $actionName = 'edit';
175  }
176 
177  // Trying to get a WikiPage for NS_SPECIAL etc. will result
178  // in WikiPage::factory throwing "Invalid or virtual namespace -1 given."
179  // For SpecialPages et al, default to action=view.
180  if ( !$context->canUseWikiPage() ) {
181  return 'view';
182  }
183 
184  $action = self::factory(
185  $actionName,
187  $context
188  );
189 
190  if ( $action instanceof Action ) {
191  return $action->getName();
192  }
193 
194  return 'nosuchaction';
195  }
196 
204  final public static function exists( string $name ) : bool {
205  return self::getClass( $name, [] ) !== null;
206  }
207 
213  final public function getContext() {
214  if ( $this->context instanceof IContextSource ) {
215  return $this->context;
216  }
217  wfDebug( __METHOD__ . ": no context known, falling back to Article's context." );
218  return $this->getArticle()->getContext();
219  }
220 
227  final public function getRequest() {
228  return $this->getContext()->getRequest();
229  }
230 
237  final public function getOutput() {
238  return $this->getContext()->getOutput();
239  }
240 
247  final public function getUser() {
248  return $this->getContext()->getUser();
249  }
250 
257  final public function getSkin() {
258  return $this->getContext()->getSkin();
259  }
260 
266  final public function getLanguage() {
267  return $this->getContext()->getLanguage();
268  }
269 
276  final public function getWikiPage() : WikiPage {
277  return $this->getArticle()->getPage();
278  }
279 
287  public function getArticle() {
288  return $this->article;
289  }
290 
297  final public function getTitle() {
298  return $this->getWikiPage()->getTitle();
299  }
300 
309  final public function msg( $key, ...$params ) {
310  return $this->getContext()->msg( $key, ...$params );
311  }
312 
317  protected function getHookContainer() {
318  return MediaWikiServices::getInstance()->getHookContainer();
319  }
320 
327  protected function getHookRunner() {
328  return new HookRunner( $this->getHookContainer() );
329  }
330 
338  public function __construct(
339  Page $page,
340  IContextSource $context = null
341  ) {
342  if ( $context === null ) {
343  wfWarn( __METHOD__ . ' called without providing a Context object.' );
344  }
345 
346  $this->page = $page;// @todo remove b/c
347  $this->article = self::convertPageToArticle( $page, $context, __METHOD__ );
348  $this->context = $context;
349  }
350 
351  private static function convertPageToArticle(
352  Page $page,
354  string $method
355  ) : Article {
356  if ( $page instanceof Article ) {
357  return $page;
358  }
359 
360  if ( !$page instanceof WikiPage ) {
361  throw new LogicException(
362  $method . ' called with unknown Page: ' . get_class( $page )
363  );
364  }
365 
366  wfDeprecated(
367  $method . ' with: ' . get_class( $page ),
368  '1.35'
369  );
370 
372  $page,
374  );
375  }
376 
383  abstract public function getName();
384 
392  public function getRestriction() {
393  return null;
394  }
395 
405  protected function checkCanExecute( User $user ) {
406  $right = $this->getRestriction();
407  if ( $right !== null ) {
408  $errors = MediaWikiServices::getInstance()->getPermissionManager()
409  ->getPermissionErrors( $right, $user, $this->getTitle() );
410  if ( count( $errors ) ) {
411  throw new PermissionsError( $right, $errors );
412  }
413  }
414 
415  // If the action requires an unblock, explicitly check the user's block.
416  if ( $this->requiresUnblock() && $user->isBlockedFrom( $this->getTitle() ) ) {
417  $block = $user->getBlock();
418  if ( $block ) {
419  throw new UserBlockedError(
420  $block,
421  $user,
422  $this->getLanguage(),
423  $this->getRequest()->getIP()
424  );
425  }
426 
427  throw new PermissionsError( $this->getName(), [ 'badaccess-group0' ] );
428  }
429 
430  // This should be checked at the end so that the user won't think the
431  // error is only temporary when he also don't have the rights to execute
432  // this action
433  if ( $this->requiresWrite() && wfReadOnly() ) {
434  throw new ReadOnlyError();
435  }
436  }
437 
444  public function requiresWrite() {
445  return true;
446  }
447 
454  public function requiresUnblock() {
455  return true;
456  }
457 
463  protected function setHeaders() {
464  $out = $this->getOutput();
465  $out->setRobotPolicy( 'noindex,nofollow' );
466  $out->setPageTitle( $this->getPageTitle() );
467  $out->setSubtitle( $this->getDescription() );
468  $out->setArticleRelated( true );
469  }
470 
476  protected function getPageTitle() {
477  return $this->getTitle()->getPrefixedText();
478  }
479 
486  protected function getDescription() {
487  return $this->msg( strtolower( $this->getName() ) )->escaped();
488  }
489 
498  public function addHelpLink( $to, $overrideBaseUrl = false ) {
499  $msg = wfMessage( MediaWikiServices::getInstance()->getContentLanguage()->lc(
500  self::getActionName( $this->getContext() )
501  ) . '-helppage' );
502 
503  if ( !$msg->isDisabled() ) {
504  $helpUrl = Skin::makeUrl( $msg->plain() );
505  $this->getOutput()->addHelpLink( $helpUrl, true );
506  } else {
507  $this->getOutput()->addHelpLink( $to, $overrideBaseUrl );
508  }
509  }
510 
519  abstract public function show();
520 
525  protected function useTransactionalTimeLimit() {
526  if ( $this->getRequest()->wasPosted() ) {
528  }
529  }
530 
536  public function doesWrites() {
537  return false;
538  }
539 }
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:152
$wgActions
$wgActions
Array of allowed values for the "title=foo&action=<action>" parameter.
Definition: DefaultSettings.php:8333
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:338
UserBlockedError
Show an error when the user tries to do something whilst blocked.
Definition: UserBlockedError.php:30
Action\getDescription
getDescription()
Returns the description that goes below the <h1> tag.
Definition: Action.php:486
Action\setHeaders
setHeaders()
Set output headers for noindexing etc.
Definition: Action.php:463
User\isBlockedFrom
isBlockedFrom( $title, $fromReplica=false)
Check if user is blocked from editing a particular article.
Definition: User.php:1965
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:149
Action\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: Action.php:227
Action\doesWrites
doesWrites()
Indicates whether this action may perform database writes.
Definition: Action.php:536
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:49
Action\exists
static exists(string $name)
Check if a given action is recognised, even if it's disabled.
Definition: Action.php:204
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:1104
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1198
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:80
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:30
Action\factory
static factory(?string $action, Page $article, IContextSource $context=null)
Get an appropriate Action subclass for the given action.
Definition: Action.php:113
MessageLocalizer
Interface for localizing messages in MediaWiki.
Definition: MessageLocalizer.php:27
Action
Actions are things which can be done to pages (edit, delete, rollback, etc).
Definition: Action.php:41
Action\getContext
getContext()
Get the IContextSource in use here.
Definition: Action.php:213
Article\newFromWikiPage
static newFromWikiPage(WikiPage $page, IContextSource $context)
Create an Article object of the appropriate class for the given page.
Definition: Article.php:227
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:1030
Action\getArticle
getArticle()
Get a Article object.
Definition: Action.php:287
wfTransactionalTimeLimit
wfTransactionalTimeLimit()
Set PHP's time limit to the larger of php.ini or $wgTransactionalTimeLimit.
Definition: GlobalFunctions.php:2687
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:405
Action\convertPageToArticle
static convertPageToArticle(Page $page, ?IContextSource $context, string $method)
Definition: Action.php:351
User\getBlock
getBlock( $fromReplica=true)
Get the block affecting the user, or null if the user is not blocked.
Definition: User.php:1949
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\getWikiPage
getWikiPage()
Get a WikiPage object.
Definition: Action.php:276
Action\$article
Article $article
Definition: Action.php:57
Action\getUser
getUser()
Shortcut to get the User being used for this instance.
Definition: Action.php:247
Action\$context
IContextSource $context
IContextSource if specified; otherwise we'll use the Context from the Page.
Definition: Action.php:64
Action\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: Action.php:498
Action\getTitle
getTitle()
Shortcut to get the Title object from the page.
Definition: Action.php:297
Action\requiresUnblock
requiresUnblock()
Whether this action can still be executed by a blocked user.
Definition: Action.php:454
Action\show
show()
The main action entry point.
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:451
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:53
Action\getHookRunner
getHookRunner()
Definition: Action.php:327
Skin\makeUrl
static makeUrl( $name, $urlaction='')
Definition: Skin.php:1233
Action\getSkin
getSkin()
Shortcut to get the Skin being used for this instance.
Definition: Action.php:257
Action\$page
WikiPage Article ImagePage CategoryPage Page $page
Page on which we're performing the action.
Definition: Action.php:51
Action\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: Action.php:309
Action\getLanguage
getLanguage()
Shortcut to get the user Language being used for this instance.
Definition: Action.php:266
Action\requiresWrite
requiresWrite()
Whether this action requires the wiki not to be locked.
Definition: Action.php:444
Action\$fields
array $fields
The fields used to create the HTMLForm.
Definition: Action.php:71
Article\getActionOverrides
getActionOverrides()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2511
Action\getPageTitle
getPageTitle()
Returns the name that goes in the <h1> page title.
Definition: Action.php:476
Action\getRestriction
getRestriction()
Get the permission required to perform this action.
Definition: Action.php:392
Action\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: Action.php:237
IContextSource\getRequest
getRequest()
Action\useTransactionalTimeLimit
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
Definition: Action.php:525
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:1051
MediaWiki\HookContainer\HookRunner
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Definition: HookRunner.php:563
Article
Class for viewing MediaWiki article and history.
Definition: Article.php:46
Action\getHookContainer
getHookContainer()
Definition: Action.php:317
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:55