MediaWiki  master
WatchAction.php
Go to the documentation of this file.
1 <?php
24 
30 class WatchAction extends FormAction {
31 
33  protected $watchlistExpiry;
34 
36  protected $expiryFormFieldName = 'expiry';
37 
39  protected $watchedItem = false;
40 
47  public function __construct( Page $page, IContextSource $context = null ) {
48  parent::__construct( $page, $context );
49  $this->watchlistExpiry = $this->getContext()->getConfig()->get( 'WatchlistExpiry' );
50  if ( $this->watchlistExpiry ) {
51  // The watchedItem is only used in this action's form if $wgWatchlistExpiry is enabled.
52  $this->watchedItem = MediaWikiServices::getInstance()
53  ->getWatchedItemStore()
54  ->getWatchedItem( $this->getUser(), $this->getTitle() );
55  }
56  }
57 
58  public function getName() {
59  return 'watch';
60  }
61 
62  public function requiresUnblock() {
63  return false;
64  }
65 
66  protected function getDescription() {
67  return '';
68  }
69 
70  public function onSubmit( $data ) {
71  $expiry = $this->getRequest()->getText( 'wp' . $this->expiryFormFieldName );
72  return self::doWatch( $this->getTitle(), $this->getUser(), User::CHECK_USER_RIGHTS, $expiry );
73  }
74 
75  protected function checkCanExecute( User $user ) {
76  // Must be logged in
77  if ( $user->isAnon() ) {
78  throw new UserNotLoggedIn( 'watchlistanontext', 'watchnologin' );
79  }
80 
81  parent::checkCanExecute( $user );
82  }
83 
84  protected function usesOOUI() {
85  return true;
86  }
87 
88  protected function getFormFields() {
89  // If watchlist expiry is not enabled, return a simple confirmation message.
90  if ( !$this->watchlistExpiry ) {
91  return [
92  'intro' => [
93  'type' => 'info',
94  'vertical-label' => true,
95  'raw' => true,
96  'default' => $this->msg( 'confirm-watch-top' )->parse(),
97  ],
98  ];
99  }
100 
101  // Otherwise, use a select-list of expiries.
102  $expiry = false;
103  if ( $this->watchedItem && $this->watchedItem->getExpiry() ) {
104  $expiry = $this->watchedItem->getExpiry();
105  }
106  $expiryOptions = static::getExpiryOptions( $this->getContext(), $expiry );
107  return [
108  $this->expiryFormFieldName => [
109  'type' => 'select',
110  'label-message' => 'confirm-watch-label',
111  'options' => $expiryOptions['options'],
112  'default' => $expiryOptions['default'],
113  ]
114  ];
115  }
116 
128  public static function getExpiryOptions( IContextSource $context, $expiryTime = false ) {
129  $expiryOptionsMsg = $context->msg( 'watchlist-expiry-options' )->text();
130  $expiryOptions = XmlSelect::parseOptionsMessage( $expiryOptionsMsg );
131  $default = 'infinite';
132  if ( $expiryTime ) {
133  // If it's already being temporarily watched,
134  // add the existing expiry as the default option in the dropdown.
136  $diffInSeconds = $expiry->getTimestamp() - wfTimestamp();
137  $diffInDays = $context
138  ->getLanguage()
139  ->getDurationIntervals( $diffInSeconds, [ 'days' ] )[ 'days' ];
140  $daysLeft = $context->msg( 'watchlist-expiry-days-left', [ $diffInDays ] )->text();
141  $expiryOptions = array_merge(
142  [ $daysLeft => $expiry->getTimestamp() ],
143  $expiryOptions
144  );
145  $default = $expiry->getTimestamp();
146  }
147  return [
148  'options' => $expiryOptions,
149  'default' => $default,
150  ];
151  }
152 
153  protected function alterForm( HTMLForm $form ) {
154  $msg = $this->watchlistExpiry && $this->watchedItem ? 'updatewatchlist' : 'addwatch';
155  $form->setWrapperLegendMsg( $msg );
156  $submitMsg = $this->watchlistExpiry ? 'confirm-watch-button-expiry' : 'confirm-watch-button';
157  $form->setSubmitTextMsg( $submitMsg );
158  $form->setTokenSalt( 'watch' );
159  }
160 
161  public function onSuccess() {
162  $msgKey = $this->getTitle()->isTalkPage() ? 'addedwatchtext-talk' : 'addedwatchtext';
163  $this->getOutput()->addWikiMsg( $msgKey, $this->getTitle()->getPrefixedText() );
164  }
165 
174  public static function doWatchOrUnwatch( $watch, Title $title, User $user ) {
175  if ( $user->isLoggedIn() &&
176  $user->isWatched( $title, User::IGNORE_USER_RIGHTS ) != $watch
177  ) {
178  // If the user doesn't have 'editmywatchlist', we still want to
179  // allow them to add but not remove items via edits and such.
180  if ( $watch ) {
182  } else {
183  return self::doUnwatch( $title, $user );
184  }
185  }
186 
187  return Status::newGood();
188  }
189 
201  public static function doWatch(
202  Title $title,
203  User $user,
204  $checkRights = User::CHECK_USER_RIGHTS,
205  ?string $expiry = null
206  ) {
207  $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
208  if ( $checkRights && !$permissionManager->userHasRight( $user, 'editmywatchlist' ) ) {
209  return User::newFatalPermissionDeniedStatus( 'editmywatchlist' );
210  }
211 
213 
214  $status = Status::newFatal( 'hookaborted' );
215  if ( Hooks::runner()->onWatchArticle( $user, $page, $status, $expiry ) ) {
216  $status = Status::newGood();
217  $user->addWatch( $title, $checkRights, $expiry );
218  Hooks::runner()->onWatchArticleComplete( $user, $page );
219  }
220 
221  return $status;
222  }
223 
231  public static function doUnwatch( Title $title, User $user ) {
232  if ( !MediaWikiServices::getInstance()
234  ->userHasRight( $user, 'editmywatchlist' ) ) {
235  return User::newFatalPermissionDeniedStatus( 'editmywatchlist' );
236  }
237 
239 
240  $status = Status::newFatal( 'hookaborted' );
241  if ( Hooks::runner()->onUnwatchArticle( $user, $page, $status ) ) {
242  $status = Status::newGood();
243  $user->removeWatch( $title );
244  Hooks::runner()->onUnwatchArticleComplete( $user, $page );
245  }
246 
247  return $status;
248  }
249 
259  public static function getWatchToken( Title $title, User $user, $action = 'watch' ) {
260  if ( $action != 'unwatch' ) {
261  $action = 'watch';
262  }
263  // This must match ApiWatch and ResourceLoaderUserOptionsModule
264  return $user->getEditToken( $action );
265  }
266 
267  public function doesWrites() {
268  return true;
269  }
270 }
Page
Interface for type hinting (accepts WikiPage, Article, ImagePage, CategoryPage)
Definition: Page.php:30
WatchAction\getExpiryOptions
static getExpiryOptions(IContextSource $context, $expiryTime=false)
Get options and default for a watchlist expiry select list.
Definition: WatchAction.php:128
StatusValue\newFatal
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:69
WatchAction\doWatch
static doWatch(Title $title, User $user, $checkRights=User::CHECK_USER_RIGHTS, ?string $expiry=null)
Watch a page.
Definition: WatchAction.php:201
User\isAnon
isAnon()
Get whether the user is anonymous.
Definition: User.php:3135
WatchAction\alterForm
alterForm(HTMLForm $form)
Play with the HTMLForm if you need to more substantially.
Definition: WatchAction.php:153
WatchAction\onSuccess
onSuccess()
Do something exciting on successful processing of the form.
Definition: WatchAction.php:161
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
User\newFatalPermissionDeniedStatus
static newFatalPermissionDeniedStatus( $permission)
Factory function for fatal permission-denied errors.
Definition: User.php:4642
WatchAction\requiresUnblock
requiresUnblock()
Whether this action can still be executed by a blocked user.
Definition: WatchAction.php:62
WatchAction\doUnwatch
static doUnwatch(Title $title, User $user)
Unwatch a page.
Definition: WatchAction.php:231
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1806
UserNotLoggedIn
Redirect a user to the login page.
Definition: UserNotLoggedIn.php:53
WatchAction\$expiryFormFieldName
string $expiryFormFieldName
Definition: WatchAction.php:36
HTMLForm\setTokenSalt
setTokenSalt( $salt)
Set the salt for the edit token.
Definition: HTMLForm.php:1037
FormAction
An action which shows a form and does something based on the input from the form.
Definition: FormAction.php:28
WatchAction\getDescription
getDescription()
Returns the description that goes below the <h1> tag.
Definition: WatchAction.php:66
WatchAction
Page addition to a user's watchlist.
Definition: WatchAction.php:30
XmlSelect\parseOptionsMessage
static parseOptionsMessage(string $msg)
Parse labels and values out of a comma- and colon-separated list of options, such as is used for expi...
Definition: XmlSelect.php:145
WatchAction\onSubmit
onSubmit( $data)
Process the form on POST submission.
Definition: WatchAction.php:70
WatchAction\getFormFields
getFormFields()
Get an HTMLForm descriptor array.
Definition: WatchAction.php:88
Action\getContext
getContext()
Get the IContextSource in use here.
Definition: Action.php:213
WatchAction\doesWrites
doesWrites()
Indicates whether this action may perform database writes.
Definition: WatchAction.php:267
WikiPage\factory
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:146
MessageLocalizer\msg
msg( $key,... $params)
This is the method for getting translated interface messages.
WatchAction\checkCanExecute
checkCanExecute(User $user)
Checks if the given user (identified by an object) can perform this action.
Definition: WatchAction.php:75
getPermissionManager
getPermissionManager()
WatchAction\doWatchOrUnwatch
static doWatchOrUnwatch( $watch, Title $title, User $user)
Watch or unwatch a page.
Definition: WatchAction.php:174
MWTimestamp\getInstance
static getInstance( $ts=false)
Get a timestamp instance in GMT.
Definition: MWTimestamp.php:39
$title
$title
Definition: testCompression.php:38
User\CHECK_USER_RIGHTS
const CHECK_USER_RIGHTS
Definition: User.php:84
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
WatchAction\$watchlistExpiry
bool $watchlistExpiry
The value of the $wgWatchlistExpiry configuration variable.
Definition: WatchAction.php:33
$expiryTime
$expiryTime
Definition: opensearch_desc.php:49
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:81
Hooks\runner
static runner()
Get a HookRunner instance for calling hooks using the new interfaces.
Definition: Hooks.php:171
WatchedItem
Representation of a pair of user and title for watchlist entries.
Definition: WatchedItem.php:33
User\addWatch
addWatch( $title, $checkRights=self::CHECK_USER_RIGHTS, ?string $expiry=null)
Watch an article.
Definition: User.php:3304
Action\getTitle
getTitle()
Shortcut to get the Title object from the page.
Definition: Action.php:297
User\removeWatch
removeWatch( $title, $checkRights=self::CHECK_USER_RIGHTS)
Stop watching an article.
Definition: User.php:3326
WatchAction\__construct
__construct(Page $page, IContextSource $context=null)
Only public since 1.21.
Definition: WatchAction.php:47
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:53
WatchAction\getName
getName()
Return the name of the action this object responds to.
Definition: WatchAction.php:58
HTMLForm\setSubmitTextMsg
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
Definition: HTMLForm.php:1388
Title
Represents a title within MediaWiki.
Definition: Title.php:42
Action\$page
WikiPage Article ImagePage CategoryPage Page $page
Page on which we're performing the action.
Definition: Action.php:51
User\isLoggedIn
isLoggedIn()
Get whether the user is logged in.
Definition: User.php:3127
Action\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: Action.php:309
HTMLForm\setWrapperLegendMsg
setWrapperLegendMsg( $msg)
Prompt the whole form to be wrapped in a "<fieldset>", with this message as its "<legend>" element.
Definition: HTMLForm.php:1575
Action\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: Action.php:237
WatchAction\getWatchToken
static getWatchToken(Title $title, User $user, $action='watch')
Get token to watch (or unwatch) a page for a user.
Definition: WatchAction.php:259
User\IGNORE_USER_RIGHTS
const IGNORE_USER_RIGHTS
Definition: User.php:89
User\isWatched
isWatched( $title, $checkRights=self::CHECK_USER_RIGHTS)
Check the watched status of an article.
Definition: User.php:3270
WatchAction\$watchedItem
false WatchedItem $watchedItem
Definition: WatchAction.php:39
User\getEditToken
getEditToken( $salt='', $request=null)
Initialize (if necessary) and return a session token value which can be used in edit forms to show th...
Definition: User.php:3942
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:55
IContextSource\getLanguage
getLanguage()
WatchAction\usesOOUI
usesOOUI()
Whether the form should use OOUI.
Definition: WatchAction.php:84
HTMLForm
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition: HTMLForm.php:133