MediaWiki  master
ApiWatch.php
Go to the documentation of this file.
1 <?php
27 
33 class ApiWatch extends ApiBase {
34  private $mPageSet = null;
35 
37  private $expiryEnabled;
38 
40  private $maxDuration;
41 
43  protected $watchlistManager;
44 
45  public function __construct( ApiMain $mainModule, $moduleName, WatchlistManager $watchlistManager ) {
46  parent::__construct( $mainModule, $moduleName );
47 
48  $this->watchlistManager = $watchlistManager;
49  $this->expiryEnabled = $this->getConfig()->get( MainConfigNames::WatchlistExpiry );
50  $this->maxDuration = $this->getConfig()->get( MainConfigNames::WatchlistExpiryMaxDuration );
51  }
52 
53  public function execute() {
54  $user = $this->getUser();
55  if ( !$user->isRegistered() ) {
56  $this->dieWithError( 'watchlistanontext', 'notloggedin' );
57  }
58 
59  $this->checkUserRightsAny( 'editmywatchlist' );
60 
61  $params = $this->extractRequestParams();
62 
63  $continuationManager = new ApiContinuationManager( $this, [], [] );
64  $this->setContinuationManager( $continuationManager );
65 
66  $pageSet = $this->getPageSet();
67  // by default we use pageset to extract the page to work on.
68  // title is still supported for backward compatibility
69  if ( !isset( $params['title'] ) ) {
70  $pageSet->execute();
71  $res = $pageSet->getInvalidTitlesAndRevisions( [
72  'invalidTitles',
73  'special',
74  'missingIds',
75  'missingRevIds',
76  'interwikiTitles'
77  ] );
78 
79  foreach ( $pageSet->getMissingTitles() as $title ) {
80  $r = $this->watchTitle( $title, $user, $params );
81  $r['missing'] = true;
82  $res[] = $r;
83  }
84 
85  foreach ( $pageSet->getGoodTitles() as $title ) {
86  $r = $this->watchTitle( $title, $user, $params );
87  $res[] = $r;
88  }
90  } else {
91  // dont allow use of old title parameter with new pageset parameters.
92  $extraParams = array_keys( array_filter( $pageSet->extractRequestParams(), static function ( $x ) {
93  return $x !== null && $x !== false;
94  } ) );
95 
96  if ( $extraParams ) {
97  $this->dieWithError(
98  [
99  'apierror-invalidparammix-cannotusewith',
100  $this->encodeParamName( 'title' ),
101  $pageSet->encodeParamName( $extraParams[0] )
102  ],
103  'invalidparammix'
104  );
105  }
106 
107  $title = Title::newFromText( $params['title'] );
108  if ( !$title || !$this->watchlistManager->isWatchable( $title ) ) {
109  $this->dieWithError( [ 'invalidtitle', $params['title'] ] );
110  }
111  $res = $this->watchTitle( $title, $user, $params, true );
112  }
113  $this->getResult()->addValue( null, $this->getModuleName(), $res );
114 
115  $this->setContinuationManager( null );
116  $continuationManager->setContinuationIntoResult( $this->getResult() );
117  }
118 
119  private function watchTitle( Title $title, User $user, array $params,
120  $compatibilityMode = false
121  ) {
122  $res = [ 'title' => $title->getPrefixedText(), 'ns' => $title->getNamespace() ];
123 
124  if ( !$this->watchlistManager->isWatchable( $title ) ) {
125  $res['watchable'] = 0;
126  return $res;
127  }
128 
129  if ( $params['unwatch'] ) {
130  $status = $this->watchlistManager->removeWatch( $user, $title );
131  $res['unwatched'] = $status->isOK();
132  } else {
133  $expiry = null;
134 
135  // NOTE: If an expiry parameter isn't given, any existing expiries remain unchanged.
136  if ( $this->expiryEnabled && isset( $params['expiry'] ) ) {
137  $expiry = $params['expiry'];
138  $res['expiry'] = ApiResult::formatExpiry( $expiry );
139  }
140 
141  $status = $this->watchlistManager->addWatch( $user, $title, $expiry );
142  $res['watched'] = $status->isOK();
143  }
144 
145  if ( !$status->isOK() ) {
146  if ( $compatibilityMode ) {
147  $this->dieStatus( $status );
148  }
149  $res['errors'] = $this->getErrorFormatter()->arrayFromStatus( $status, 'error' );
150  $res['warnings'] = $this->getErrorFormatter()->arrayFromStatus( $status, 'warning' );
151  if ( !$res['warnings'] ) {
152  unset( $res['warnings'] );
153  }
154  }
155 
156  return $res;
157  }
158 
163  private function getPageSet() {
164  if ( $this->mPageSet === null ) {
165  $this->mPageSet = new ApiPageSet( $this );
166  }
167 
168  return $this->mPageSet;
169  }
170 
171  public function mustBePosted() {
172  return true;
173  }
174 
175  public function isWriteMode() {
176  return true;
177  }
178 
179  public function needsToken() {
180  return 'watch';
181  }
182 
183  public function getAllowedParams( $flags = 0 ) {
184  $result = [
185  'title' => [
186  ParamValidator::PARAM_TYPE => 'string',
187  ParamValidator::PARAM_DEPRECATED => true,
188  ],
189  'expiry' => [
190  ParamValidator::PARAM_TYPE => 'expiry',
191  ExpiryDef::PARAM_MAX => $this->maxDuration,
192  ExpiryDef::PARAM_USE_MAX => true,
193  ],
194  'unwatch' => false,
195  'continue' => [
196  ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
197  ],
198  ];
199 
200  // If expiry is not enabled, don't accept the parameter.
201  if ( !$this->expiryEnabled ) {
202  unset( $result['expiry'] );
203  }
204 
205  if ( $flags ) {
206  $result += $this->getPageSet()->getFinalParams( $flags );
207  }
208 
209  return $result;
210  }
211 
212  protected function getExamplesMessages() {
213  // Logically expiry example should go before unwatch examples.
214  $examples = [
215  'action=watch&titles=Main_Page&token=123ABC'
216  => 'apihelp-watch-example-watch',
217  ];
218  if ( $this->expiryEnabled ) {
219  $examples['action=watch&titles=Main_Page|Foo|Bar&expiry=1%20month&token=123ABC']
220  = 'apihelp-watch-example-watch-expiry';
221  }
222 
223  return array_merge( $examples, [
224  'action=watch&titles=Main_Page&unwatch=&token=123ABC'
225  => 'apihelp-watch-example-unwatch',
226  'action=watch&generator=allpages&gapnamespace=0&token=123ABC'
227  => 'apihelp-watch-example-generator',
228  ] );
229  }
230 
231  public function getHelpUrls() {
232  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Watch';
233  }
234 }
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:56
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
Definition: ApiBase.php:1458
checkUserRightsAny( $rights, $user=null)
Helper function for permission-denied errors.
Definition: ApiBase.php:1567
encodeParamName( $paramName)
This method mangles parameter name based on the prefix supplied to the constructor.
Definition: ApiBase.php:743
getErrorFormatter()
Definition: ApiBase.php:640
setContinuationManager(ApiContinuationManager $manager=null)
Definition: ApiBase.php:673
getResult()
Get the result object.
Definition: ApiBase.php:629
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:765
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition: ApiBase.php:163
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:498
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
Definition: ApiBase.php:1521
This manages continuation state.
This is the main API class, used for both external and internal processing.
Definition: ApiMain.php:52
This class contains a list of pages that the client has requested.
Definition: ApiPageSet.php:50
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:604
static formatExpiry( $expiry, $infinity='infinity')
Format an expiry timestamp for API output.
Definition: ApiResult.php:1199
API module to allow users to watch a page.
Definition: ApiWatch.php:33
getAllowedParams( $flags=0)
Definition: ApiWatch.php:183
isWriteMode()
Indicates whether this module requires write mode.
Definition: ApiWatch.php:175
__construct(ApiMain $mainModule, $moduleName, WatchlistManager $watchlistManager)
Definition: ApiWatch.php:45
needsToken()
Returns the token type this module requires in order to execute.
Definition: ApiWatch.php:179
getHelpUrls()
Return links to more detailed help pages about the module.
Definition: ApiWatch.php:231
getExamplesMessages()
Returns usage examples for this module.
Definition: ApiWatch.php:212
mustBePosted()
Indicates whether this module must be called with a POST request.
Definition: ApiWatch.php:171
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
Definition: ApiWatch.php:53
WatchlistManager $watchlistManager
Definition: ApiWatch.php:43
A class containing constants representing the names of configuration variables.
Represents a title within MediaWiki.
Definition: Title.php:49
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:370
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:70
isRegistered()
Get whether the user is registered.
Definition: User.php:2328
Service for formatting and validating API parameters.
Type definition for expiry timestamps.
Definition: ExpiryDef.php:17