MediaWiki  master
WatchAction.php
Go to the documentation of this file.
1 <?php
28 
34 class WatchAction extends FormAction {
35 
37  protected $watchlistExpiry;
38 
40  protected $expiryFormFieldName = 'expiry';
41 
43  protected $watchedItem = false;
44 
47 
56  public function __construct(
57  Page $page,
60  WatchedItemStore $watchedItemStore
61  ) {
62  parent::__construct( $page, $context );
63  $this->watchlistExpiry = $this->getContext()->getConfig()->get( 'WatchlistExpiry' );
64  if ( $this->watchlistExpiry ) {
65  // The watchedItem is only used in this action's form if $wgWatchlistExpiry is enabled.
66  $this->watchedItem = $watchedItemStore->getWatchedItem(
67  $this->getUser(),
68  $this->getTitle()
69  );
70  }
71  $this->watchlistManager = $watchlistManager;
72  }
73 
74  public function getName() {
75  return 'watch';
76  }
77 
78  public function requiresUnblock() {
79  return false;
80  }
81 
82  protected function getDescription() {
83  return '';
84  }
85 
86  public function onSubmit( $data ) {
87  $expiry = $this->getRequest()->getVal( 'wp' . $this->expiryFormFieldName );
88 
89  // Even though we're never unwatching here, use WatchlistManager::setWatch() because it also checks for
90  // changed expiry.
91  return $this->watchlistManager->setWatch(
92  true,
93  $this->getContext()->getAuthority(),
94  $this->getTitle(),
95  $expiry
96  );
97  }
98 
99  protected function checkCanExecute( User $user ) {
100  // Must be logged in
101  if ( $user->isAnon() ) {
102  throw new UserNotLoggedIn( 'watchlistanontext', 'watchnologin' );
103  }
104 
105  parent::checkCanExecute( $user );
106  }
107 
108  protected function usesOOUI() {
109  return true;
110  }
111 
112  protected function getFormFields() {
113  // If watchlist expiry is not enabled, return a simple confirmation message.
114  if ( !$this->watchlistExpiry ) {
115  return [
116  'intro' => [
117  'type' => 'info',
118  'raw' => true,
119  'default' => $this->msg( 'confirm-watch-top' )->parse(),
120  ],
121  ];
122  }
123 
124  // Otherwise, use a select-list of expiries.
125  $expiryOptions = static::getExpiryOptions( $this->getContext(), $this->watchedItem );
126  return [
127  $this->expiryFormFieldName => [
128  'type' => 'select',
129  'label-message' => 'confirm-watch-label',
130  'options' => $expiryOptions['options'],
131  'default' => $expiryOptions['default'],
132  ]
133  ];
134  }
135 
148  public static function getExpiryOptions( MessageLocalizer $msgLocalizer, $watchedItem ) {
149  $expiryOptions = self::getExpiryOptionsFromMessage( $msgLocalizer );
150  $default = in_array( 'infinite', $expiryOptions )
151  ? 'infinite'
152  : current( $expiryOptions );
153  if ( $watchedItem instanceof WatchedItem && $watchedItem->getExpiry() ) {
154  // If it's already being temporarily watched,
155  // add the existing expiry as the default option in the dropdown.
156  $default = $watchedItem->getExpiry( TS_ISO_8601 );
157  $daysLeft = $watchedItem->getExpiryInDaysText( $msgLocalizer, true );
158  $expiryOptions = array_merge( [ $daysLeft => $default ], $expiryOptions );
159  }
160  return [
161  'options' => $expiryOptions,
162  'default' => $default,
163  ];
164  }
165 
174  private static function getExpiryOptionsFromMessage(
175  MessageLocalizer $msgLocalizer, ?string $lang = null
176  ): array {
177  $expiryOptionsMsg = $msgLocalizer->msg( 'watchlist-expiry-options' );
178  $optionsText = !$lang ? $expiryOptionsMsg->text() : $expiryOptionsMsg->inLanguage( $lang )->text();
180  $optionsText
181  );
182 
183  $expiryOptions = [];
184  foreach ( $options as $label => $value ) {
185  if ( strtotime( $value ) || wfIsInfinity( $value ) ) {
186  $expiryOptions[$label] = $value;
187  }
188  }
189 
190  // If message options is invalid try to recover by returning
191  // english options (T267611)
192  if ( !$expiryOptions && $expiryOptionsMsg->getLanguage()->getCode() !== 'en' ) {
193  return self::getExpiryOptionsFromMessage( $msgLocalizer, 'en' );
194  }
195 
196  return $expiryOptions;
197  }
198 
199  protected function alterForm( HTMLForm $form ) {
200  $msg = $this->watchlistExpiry && $this->watchedItem ? 'updatewatchlist' : 'addwatch';
201  $form->setWrapperLegendMsg( $msg );
202  $submitMsg = $this->watchlistExpiry ? 'confirm-watch-button-expiry' : 'confirm-watch-button';
203  $form->setSubmitTextMsg( $submitMsg );
204  $form->setTokenSalt( 'watch' );
205  }
206 
219  public function onSuccess() {
220  $msgKey = $this->getTitle()->isTalkPage() ? 'addedwatchtext-talk' : 'addedwatchtext';
221  $expiryLabel = null;
222  $submittedExpiry = $this->getContext()->getRequest()->getText( 'wp' . $this->expiryFormFieldName );
223  if ( $submittedExpiry ) {
224  // We can't use $this->watcheditem to get the expiry because it's not been saved at this
225  // point in the request and so its values are those from before saving.
226  $expiry = ExpiryDef::normalizeExpiry( $submittedExpiry, TS_ISO_8601 );
227 
228  // If the expiry label isn't one of the predefined ones in the dropdown, calculate 'x days'.
229  $expiryDays = WatchedItem::calculateExpiryInDays( $expiry );
230  $defaultLabels = static::getExpiryOptions( $this->getContext(), null )['options'];
231  $localizedExpiry = array_search( $submittedExpiry, $defaultLabels );
232  $expiryLabel = $expiryDays && $localizedExpiry === false
233  ? $this->getContext()->msg( 'days', $expiryDays )->text()
234  : $localizedExpiry;
235 
236  // Determine which message to use, depending on whether this is a talk page or not
237  // and whether an expiry was selected.
238  $isTalk = $this->getTitle()->isTalkPage();
239  if ( wfIsInfinity( $expiry ) ) {
240  $msgKey = $isTalk ? 'addedwatchindefinitelytext-talk' : 'addedwatchindefinitelytext';
241  } elseif ( $expiryDays > 0 ) {
242  $msgKey = $isTalk ? 'addedwatchexpirytext-talk' : 'addedwatchexpirytext';
243  } elseif ( $expiryDays < 1 ) {
244  $msgKey = $isTalk ? 'addedwatchexpiryhours-talk' : 'addedwatchexpiryhours';
245  }
246  }
247  $this->getOutput()->addWikiMsg( $msgKey, $this->getTitle()->getPrefixedText(), $expiryLabel );
248  }
249 
264  public static function doWatchOrUnwatch(
265  $watch,
266  PageIdentity $pageIdentity,
267  Authority $performer,
268  string $expiry = null
269  ) {
270  wfDeprecated( __METHOD__, '1.37' );
271  return Status::wrap( MediaWikiServices::getInstance()->getWatchlistManager()->setWatch(
272  $watch,
273  $performer,
274  $pageIdentity,
275  $expiry
276  ) );
277  }
278 
291  public static function doWatch(
292  PageIdentity $pageIdentity,
293  Authority $performer,
294  $checkRights = User::CHECK_USER_RIGHTS,
295  ?string $expiry = null
296  ) {
297  wfDeprecated( __METHOD__, '1.37' );
298  $watchlistManager = MediaWikiServices::getInstance()->getWatchlistManager();
299  if ( $checkRights ) {
301  $performer,
302  $pageIdentity,
303  $expiry
304  ) );
305  }
307  $performer->getUser(),
308  $pageIdentity,
309  $expiry
310  ) );
311  }
312 
323  public static function doUnwatch( PageIdentity $pageIdentity, Authority $performer ) {
324  wfDeprecated( __METHOD__, '1.37' );
325  return Status::wrap( MediaWikiServices::getInstance()->getWatchlistManager()->removeWatch(
326  $performer,
327  $pageIdentity
328  ) );
329  }
330 
342  public static function getWatchToken( PageIdentity $page, User $user, $action = 'watch' ) {
343  wfDeprecated( __METHOD__, '1.37' );
344  if ( $action != 'unwatch' ) {
345  $action = 'watch';
346  }
347  // This must match ApiWatch and ResourceLoaderUserOptionsModule
348  return $user->getEditToken( $action );
349  }
350 
351  public function doesWrites() {
352  return true;
353  }
354 }
Page\PageIdentity
Interface for objects (potentially) representing an editable wiki page.
Definition: PageIdentity.php:64
WatchAction\$watchlistManager
WatchlistManager $watchlistManager
Definition: WatchAction.php:46
MediaWiki\Watchlist\WatchlistManager\addWatchIgnoringRights
addWatchIgnoringRights(UserIdentity $userIdentity, PageIdentity $target, ?string $expiry=null)
Watch a page.
Definition: WatchlistManager.php:406
Page
Interface for type hinting (accepts WikiPage, Article, ImagePage, CategoryPage)
Definition: Page.php:29
WatchAction\doUnwatch
static doUnwatch(PageIdentity $pageIdentity, Authority $performer)
Unwatch a page.
Definition: WatchAction.php:323
User\isAnon
isAnon()
Get whether the user is anonymous.
Definition: User.php:2985
WatchAction\alterForm
alterForm(HTMLForm $form)
Play with the HTMLForm if you need to more substantially.
Definition: WatchAction.php:199
WatchAction\onSuccess
onSuccess()
Show one of 8 possible success messages.
Definition: WatchAction.php:219
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:193
Action\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: Action.php:146
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
WatchAction\requiresUnblock
requiresUnblock()
Whether this action can still be executed by a blocked user.
Definition: WatchAction.php:78
WatchAction\doWatchOrUnwatch
static doWatchOrUnwatch( $watch, PageIdentity $pageIdentity, Authority $performer, string $expiry=null)
Watch or unwatch a page.
Definition: WatchAction.php:264
UserNotLoggedIn
Redirect a user to the login page.
Definition: UserNotLoggedIn.php:54
WatchAction\$expiryFormFieldName
string $expiryFormFieldName
Definition: WatchAction.php:40
WatchAction\getExpiryOptions
static getExpiryOptions(MessageLocalizer $msgLocalizer, $watchedItem)
Get options and default for a watchlist expiry select list.
Definition: WatchAction.php:148
HTMLForm\setTokenSalt
setTokenSalt( $salt)
Set the salt for the edit token.
Definition: HTMLForm.php:1057
getAuthority
getAuthority()
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:82
WatchAction
Page addition to a user's watchlist.
Definition: WatchAction.php:34
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:146
WatchAction\onSubmit
onSubmit( $data)
Process the form on POST submission.
Definition: WatchAction.php:86
MediaWiki\Permissions\Authority\getUser
getUser()
Returns the performer of the actions associated with this authority.
MessageLocalizer
Interface for localizing messages in MediaWiki.
Definition: MessageLocalizer.php:29
WatchAction\getFormFields
getFormFields()
Get an HTMLForm descriptor array.
Definition: WatchAction.php:112
WatchAction\doWatch
static doWatch(PageIdentity $pageIdentity, Authority $performer, $checkRights=User::CHECK_USER_RIGHTS, ?string $expiry=null)
Watch a page.
Definition: WatchAction.php:291
Action\getContext
getContext()
Get the IContextSource in use here.
Definition: Action.php:132
WatchedItem\getExpiry
getExpiry(?int $style=TS_MW)
When the watched item will expire.
Definition: WatchedItem.php:150
Wikimedia\ParamValidator\TypeDef\ExpiryDef
Type definition for expiry timestamps.
Definition: ExpiryDef.php:17
WatchAction\doesWrites
doesWrites()
Definition: WatchAction.php:351
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
Definition: GlobalFunctions.php:997
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:99
MediaWiki\Watchlist\WatchlistManager
WatchlistManager service.
Definition: WatchlistManager.php:52
Status\wrap
static wrap( $sv)
Succinct helper method to wrap a StatusValue.
Definition: Status.php:62
setWatch
setWatch(string $watch, Title $title, User $user, ?string $userOption=null, ?string $expiry=null)
Set a watch (or unwatch) based the based on a watchlist parameter.
Definition: ApiWatchlistTrait.php:96
User\CHECK_USER_RIGHTS
const CHECK_USER_RIGHTS
Definition: User.php:110
WatchedItem\calculateExpiryInDays
static calculateExpiryInDays(?string $expiry)
Get the number of days remaining until the given expiry time.
Definition: WatchedItem.php:192
MediaWiki\Permissions\Authority
This interface represents the authority associated the current execution context, such as a web reque...
Definition: Authority.php:37
WatchAction\getExpiryOptionsFromMessage
static getExpiryOptionsFromMessage(MessageLocalizer $msgLocalizer, ?string $lang=null)
Parse expiry options message.
Definition: WatchAction.php:174
Action\getUser
getUser()
Shortcut to get the User being used for this instance.
Definition: Action.php:166
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:37
wfIsInfinity
wfIsInfinity( $str)
Determine input string is represents as infinity.
Definition: GlobalFunctions.php:2524
WatchedItem
Representation of a pair of user and title for watchlist entries.
Definition: WatchedItem.php:36
Action\getTitle
getTitle()
Shortcut to get the Title object from the page.
Definition: Action.php:216
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:58
WatchAction\getName
getName()
Return the name of the action this object responds to.
Definition: WatchAction.php:74
WatchedItemStore
Storage layer class for WatchedItems.
Definition: WatchedItemStore.php:26
HTMLForm\setSubmitTextMsg
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
Definition: HTMLForm.php:1420
WatchedItem\getExpiryInDaysText
getExpiryInDaysText(MessageLocalizer $msgLocalizer, $isDropdownOption=false)
Get days remaining until a watched item expires as a text.
Definition: WatchedItem.php:218
Action\$page
WikiPage Article ImagePage CategoryPage Page $page
Page on which we're performing the action.
Definition: Action.php:53
WatchAction\__construct
__construct(Page $page, IContextSource $context, WatchlistManager $watchlistManager, WatchedItemStore $watchedItemStore)
Only public since 1.21.
Definition: WatchAction.php:56
Action\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: Action.php:228
HTMLForm\setWrapperLegendMsg
setWrapperLegendMsg( $msg)
Prompt the whole form to be wrapped in a "<fieldset>", with this message as its "<legend>" element.
Definition: HTMLForm.php:1625
Action\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: Action.php:156
WatchedItemStore\getWatchedItem
getWatchedItem(UserIdentity $user, $target)
Definition: WatchedItemStore.php:742
WatchAction\$watchedItem
false WatchedItem $watchedItem
Definition: WatchAction.php:43
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:3714
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:68
MediaWiki\Watchlist\WatchlistManager\addWatch
addWatch(Authority $performer, PageIdentity $target, ?string $expiry=null)
Watch a page if the user has permission to edit their watchlist.
Definition: WatchlistManager.php:446
WatchAction\getWatchToken
static getWatchToken(PageIdentity $page, User $user, $action='watch')
Get token to watch (or unwatch) a page for a user.
Definition: WatchAction.php:342
WatchAction\usesOOUI
usesOOUI()
Whether the form should use OOUI.
Definition: WatchAction.php:108
HTMLForm
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition: HTMLForm.php:143