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  $expiryOptions = static::getExpiryOptions( $this->getContext(), $this->watchedItem );
103  return [
104  $this->expiryFormFieldName => [
105  'type' => 'select',
106  'label-message' => 'confirm-watch-label',
107  'options' => $expiryOptions['options'],
108  'default' => $expiryOptions['default'],
109  ]
110  ];
111  }
112 
125  public static function getExpiryOptions( MessageLocalizer $msgLocalizer, $watchedItem ) {
126  $expiryOptionsMsg = $msgLocalizer->msg( 'watchlist-expiry-options' );
127  $expiryOptionsMsgText = $expiryOptionsMsg->text();
128  $expiryOptions = XmlSelect::parseOptionsMessage( $expiryOptionsMsgText );
129  $default = 'infinite';
130  if ( $watchedItem instanceof WatchedItem && $watchedItem->getExpiry() ) {
131  // If it's already being temporarily watched,
132  // add the existing expiry as the default option in the dropdown.
134  $diffInDays = $watchedItem->getExpiryInDays();
135  $daysLeft = $msgLocalizer->msg( 'watchlist-expiry-days-left', [ $diffInDays ] )->text();
136  $expiryOptions = array_merge(
137  [ $daysLeft => $expiry->getTimestamp( TS_MW ) ],
138  $expiryOptions
139  );
140  $default = $expiry->getTimestamp( TS_MW );
141  }
142  return [
143  'options' => $expiryOptions,
144  'default' => $default,
145  ];
146  }
147 
148  protected function alterForm( HTMLForm $form ) {
149  $msg = $this->watchlistExpiry && $this->watchedItem ? 'updatewatchlist' : 'addwatch';
150  $form->setWrapperLegendMsg( $msg );
151  $submitMsg = $this->watchlistExpiry ? 'confirm-watch-button-expiry' : 'confirm-watch-button';
152  $form->setSubmitTextMsg( $submitMsg );
153  $form->setTokenSalt( 'watch' );
154  }
155 
156  public function onSuccess() {
157  $msgKey = $this->getTitle()->isTalkPage() ? 'addedwatchtext-talk' : 'addedwatchtext';
158  $this->getOutput()->addWikiMsg( $msgKey, $this->getTitle()->getPrefixedText() );
159  }
160 
172  public static function doWatchOrUnwatch(
173  $watch,
174  Title $title,
175  User $user,
176  string $expiry = null
177  ) {
178  // User must be logged in, and either changing the watch state or at least the expiry.
179  if ( !$user->isLoggedIn() ) {
180  return Status::newGood();
181  }
182  $changingWatchStatus = $user->isWatched( $title, User::IGNORE_USER_RIGHTS ) !== $watch;
183  if ( $expiry !== null || $changingWatchStatus ) {
184  // If the user doesn't have 'editmywatchlist', we still want to
185  // allow them to add but not remove items via edits and such.
186  if ( $watch ) {
187  return self::doWatch( $title, $user, User::IGNORE_USER_RIGHTS, $expiry );
188  } else {
189  return self::doUnwatch( $title, $user );
190  }
191  }
192 
193  return Status::newGood();
194  }
195 
207  public static function doWatch(
208  Title $title,
209  User $user,
210  $checkRights = User::CHECK_USER_RIGHTS,
211  ?string $expiry = null
212  ) {
213  $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
214  if ( $checkRights && !$permissionManager->userHasRight( $user, 'editmywatchlist' ) ) {
215  return User::newFatalPermissionDeniedStatus( 'editmywatchlist' );
216  }
217 
219 
220  $status = Status::newFatal( 'hookaborted' );
221  if ( Hooks::runner()->onWatchArticle( $user, $page, $status, $expiry ) ) {
222  $status = Status::newGood();
223  $user->addWatch( $title, $checkRights, $expiry );
224  Hooks::runner()->onWatchArticleComplete( $user, $page );
225  }
226 
227  return $status;
228  }
229 
237  public static function doUnwatch( Title $title, User $user ) {
238  if ( !MediaWikiServices::getInstance()
240  ->userHasRight( $user, 'editmywatchlist' ) ) {
241  return User::newFatalPermissionDeniedStatus( 'editmywatchlist' );
242  }
243 
245 
246  $status = Status::newFatal( 'hookaborted' );
247  if ( Hooks::runner()->onUnwatchArticle( $user, $page, $status ) ) {
248  $status = Status::newGood();
249  $user->removeWatch( $title );
250  Hooks::runner()->onUnwatchArticleComplete( $user, $page );
251  }
252 
253  return $status;
254  }
255 
265  public static function getWatchToken( Title $title, User $user, $action = 'watch' ) {
266  if ( $action != 'unwatch' ) {
267  $action = 'watch';
268  }
269  // This must match ApiWatch and ResourceLoaderUserOptionsModule
270  return $user->getEditToken( $action );
271  }
272 
273  public function doesWrites() {
274  return true;
275  }
276 }
Page
Interface for type hinting (accepts WikiPage, Article, ImagePage, CategoryPage)
Definition: Page.php:30
StatusValue\newFatal
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:70
WatchAction\doWatch
static doWatch(Title $title, User $user, $checkRights=User::CHECK_USER_RIGHTS, ?string $expiry=null)
Watch a page.
Definition: WatchAction.php:207
User\isAnon
isAnon()
Get whether the user is anonymous.
Definition: User.php:3022
WatchAction\alterForm
alterForm(HTMLForm $form)
Play with the HTMLForm if you need to more substantially Stable to override.
Definition: WatchAction.php:148
WatchAction\onSuccess
onSuccess()
Do something exciting on successful processing of the form.
Definition: WatchAction.php:156
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
User\newFatalPermissionDeniedStatus
static newFatalPermissionDeniedStatus( $permission)
Factory function for fatal permission-denied errors.
Definition: User.php:4474
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:237
UserNotLoggedIn
Redirect a user to the login page.
Definition: UserNotLoggedIn.php:54
WatchAction\$expiryFormFieldName
string $expiryFormFieldName
Definition: WatchAction.php:36
WatchAction\getExpiryOptions
static getExpiryOptions(MessageLocalizer $msgLocalizer, $watchedItem)
Get options and default for a watchlist expiry select list.
Definition: WatchAction.php:125
HTMLForm\setTokenSalt
setTokenSalt( $salt)
Set the salt for the edit token.
Definition: HTMLForm.php:1047
FormAction
An action which shows a form and does something based on the input from the form.
Definition: FormAction.php:30
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
MessageLocalizer
Interface for localizing messages in MediaWiki.
Definition: MessageLocalizer.php:29
WatchAction\getFormFields
getFormFields()
Get an HTMLForm descriptor array Stable to override.
Definition: WatchAction.php:88
Action\getContext
getContext()
Get the IContextSource in use here.
Definition: Action.php:215
WatchAction\doesWrites
doesWrites()
Stable to override.
Definition: WatchAction.php:273
WikiPage\factory
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:156
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()
MWTimestamp\getInstance
static getInstance( $ts=false)
Get a timestamp instance in GMT.
Definition: MWTimestamp.php:41
$title
$title
Definition: testCompression.php:38
User\CHECK_USER_RIGHTS
const CHECK_USER_RIGHTS
Definition: User.php:85
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
WatchAction\$watchlistExpiry
bool $watchlistExpiry
The value of the $wgWatchlistExpiry configuration variable.
Definition: WatchAction.php:33
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:82
Hooks\runner
static runner()
Get a HookRunner instance for calling hooks using the new interfaces.
Definition: Hooks.php:172
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:3191
Action\getTitle
getTitle()
Shortcut to get the Title object from the page.
Definition: Action.php:299
User\removeWatch
removeWatch( $title, $checkRights=self::CHECK_USER_RIGHTS)
Stop watching an article.
Definition: User.php:3213
WatchAction\doWatchOrUnwatch
static doWatchOrUnwatch( $watch, Title $title, User $user, string $expiry=null)
Watch or unwatch a page.
Definition: WatchAction.php:172
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:55
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:1407
Title
Represents a title within MediaWiki.
Definition: Title.php:42
WatchedItem\getExpiry
getExpiry()
When the watched item will expire.
Definition: WatchedItem.php:134
Action\$page
WikiPage Article ImagePage CategoryPage Page $page
Page on which we're performing the action.
Definition: Action.php:53
User\isLoggedIn
isLoggedIn()
Get whether the user is logged in.
Definition: User.php:3014
Action\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: Action.php:311
HTMLForm\setWrapperLegendMsg
setWrapperLegendMsg( $msg)
Prompt the whole form to be wrapped in a "<fieldset>", with this message as its "<legend>" element.
Definition: HTMLForm.php:1594
Action\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: Action.php:239
WatchAction\getWatchToken
static getWatchToken(Title $title, User $user, $action='watch')
Get token to watch (or unwatch) a page for a user.
Definition: WatchAction.php:265
User\IGNORE_USER_RIGHTS
const IGNORE_USER_RIGHTS
Definition: User.php:90
User\isWatched
isWatched( $title, $checkRights=self::CHECK_USER_RIGHTS)
Check the watched status of an article.
Definition: User.php:3157
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:3797
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:56
WatchedItem\getExpiryInDays
getExpiryInDays()
Get days remaining until a watched item expires.
Definition: WatchedItem.php:161
WatchAction\usesOOUI
usesOOUI()
Whether the form should use OOUI Stable to override.
Definition: WatchAction.php:84
HTMLForm
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition: HTMLForm.php:135