Merge "SpecialBlock [Vue]: add NamespacesField and PagesField components"
[mediawiki.git] / includes / api / ApiQueryWatchlistRaw.php
blob428cb84f1a8fa8cef51c2d851361bafab01f0ebc
1 <?php
2 /**
3 * Copyright © 2008 Roan Kattouw <roan.kattouw@gmail.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
20 * @file
23 namespace MediaWiki\Api;
25 use MediaWiki\Cache\GenderCache;
26 use MediaWiki\Language\Language;
27 use MediaWiki\ParamValidator\TypeDef\UserDef;
28 use MediaWiki\Title\NamespaceInfo;
29 use MediaWiki\Title\Title;
30 use MediaWiki\Title\TitleValue;
31 use MediaWiki\Watchlist\WatchedItemQueryService;
32 use MediaWiki\Watchlist\WatchedItemStore;
33 use Wikimedia\ParamValidator\ParamValidator;
34 use Wikimedia\ParamValidator\TypeDef\IntegerDef;
36 /**
37 * This query action allows clients to retrieve a list of pages
38 * on the logged-in user's watchlist.
40 * @ingroup API
42 class ApiQueryWatchlistRaw extends ApiQueryGeneratorBase {
44 private WatchedItemQueryService $watchedItemQueryService;
45 private Language $contentLanguage;
46 private NamespaceInfo $namespaceInfo;
47 private GenderCache $genderCache;
49 public function __construct(
50 ApiQuery $query,
51 string $moduleName,
52 WatchedItemQueryService $watchedItemQueryService,
53 Language $contentLanguage,
54 NamespaceInfo $namespaceInfo,
55 GenderCache $genderCache
56 ) {
57 parent::__construct( $query, $moduleName, 'wr' );
58 $this->watchedItemQueryService = $watchedItemQueryService;
59 $this->contentLanguage = $contentLanguage;
60 $this->namespaceInfo = $namespaceInfo;
61 $this->genderCache = $genderCache;
64 public function execute() {
65 $this->run();
68 public function executeGenerator( $resultPageSet ) {
69 $this->run( $resultPageSet );
72 /**
73 * @param ApiPageSet|null $resultPageSet
74 * @return void
76 private function run( $resultPageSet = null ) {
77 $params = $this->extractRequestParams();
79 $user = $this->getWatchlistUser( $params );
81 $prop = array_fill_keys( (array)$params['prop'], true );
82 $show = array_fill_keys( (array)$params['show'], true );
83 if ( isset( $show[WatchedItemQueryService::FILTER_CHANGED] )
84 && isset( $show[WatchedItemQueryService::FILTER_NOT_CHANGED] )
85 ) {
86 $this->dieWithError( 'apierror-show' );
89 $options = [];
90 if ( $params['namespace'] ) {
91 $options['namespaceIds'] = $params['namespace'];
93 if ( isset( $show[WatchedItemQueryService::FILTER_CHANGED] ) ) {
94 $options['filter'] = WatchedItemQueryService::FILTER_CHANGED;
96 if ( isset( $show[WatchedItemQueryService::FILTER_NOT_CHANGED] ) ) {
97 $options['filter'] = WatchedItemQueryService::FILTER_NOT_CHANGED;
100 if ( isset( $params['continue'] ) ) {
101 $cont = $this->parseContinueParamOrDie( $params['continue'], [ 'int', 'string' ] );
102 $options['startFrom'] = TitleValue::tryNew( $cont[0], $cont[1] );
103 $this->dieContinueUsageIf( !$options['startFrom'] );
106 if ( isset( $params['fromtitle'] ) ) {
107 $options['from'] = $this->parsePrefixedTitlePart( $params['fromtitle'] );
110 if ( isset( $params['totitle'] ) ) {
111 $options['until'] = $this->parsePrefixedTitlePart( $params['totitle'] );
114 $options['sort'] = WatchedItemStore::SORT_ASC;
115 if ( $params['dir'] === 'descending' ) {
116 $options['sort'] = WatchedItemStore::SORT_DESC;
118 $options['limit'] = $params['limit'] + 1;
120 $titles = [];
121 $count = 0;
122 $items = $this->watchedItemQueryService->getWatchedItemsForUser( $user, $options );
124 // Get gender information
125 if ( $items !== [] && $resultPageSet === null &&
126 $this->contentLanguage->needsGenderDistinction()
128 $usernames = [];
129 foreach ( $items as $item ) {
130 $linkTarget = $item->getTarget();
131 if ( $this->namespaceInfo->hasGenderDistinction( $linkTarget->getNamespace() ) ) {
132 $usernames[] = $linkTarget->getText();
135 if ( $usernames !== [] ) {
136 $this->genderCache->doQuery( $usernames, __METHOD__ );
140 foreach ( $items as $item ) {
141 $ns = $item->getTarget()->getNamespace();
142 $dbKey = $item->getTarget()->getDBkey();
143 if ( ++$count > $params['limit'] ) {
144 // We've reached the one extra which shows that there are
145 // additional pages to be had. Stop here...
146 $this->setContinueEnumParameter( 'continue', $ns . '|' . $dbKey );
147 break;
149 $t = Title::makeTitle( $ns, $dbKey );
151 if ( $resultPageSet === null ) {
152 $vals = [];
153 ApiQueryBase::addTitleInfo( $vals, $t );
154 if ( isset( $prop['changed'] ) && $item->getNotificationTimestamp() !== null ) {
155 $vals['changed'] = wfTimestamp( TS_ISO_8601, $item->getNotificationTimestamp() );
157 $fit = $this->getResult()->addValue( $this->getModuleName(), null, $vals );
158 if ( !$fit ) {
159 $this->setContinueEnumParameter( 'continue', $ns . '|' . $dbKey );
160 break;
162 } else {
163 $titles[] = $t;
166 if ( $resultPageSet === null ) {
167 $this->getResult()->addIndexedTagName( $this->getModuleName(), 'wr' );
168 } else {
169 $resultPageSet->populateFromTitles( $titles );
173 public function getAllowedParams() {
174 return [
175 'continue' => [
176 ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
178 'namespace' => [
179 ParamValidator::PARAM_ISMULTI => true,
180 ParamValidator::PARAM_TYPE => 'namespace'
182 'limit' => [
183 ParamValidator::PARAM_DEFAULT => 10,
184 ParamValidator::PARAM_TYPE => 'limit',
185 IntegerDef::PARAM_MIN => 1,
186 IntegerDef::PARAM_MAX => ApiBase::LIMIT_BIG1,
187 IntegerDef::PARAM_MAX2 => ApiBase::LIMIT_BIG2
189 'prop' => [
190 ParamValidator::PARAM_ISMULTI => true,
191 ParamValidator::PARAM_TYPE => [
192 'changed',
194 ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
196 'show' => [
197 ParamValidator::PARAM_ISMULTI => true,
198 ParamValidator::PARAM_TYPE => [
199 WatchedItemQueryService::FILTER_CHANGED,
200 WatchedItemQueryService::FILTER_NOT_CHANGED
203 'owner' => [
204 ParamValidator::PARAM_TYPE => 'user',
205 UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name' ],
207 'token' => [
208 ParamValidator::PARAM_TYPE => 'string',
209 ParamValidator::PARAM_SENSITIVE => true,
211 'dir' => [
212 ParamValidator::PARAM_DEFAULT => 'ascending',
213 ParamValidator::PARAM_TYPE => [
214 'ascending',
215 'descending'
218 'fromtitle' => [
219 ParamValidator::PARAM_TYPE => 'string'
221 'totitle' => [
222 ParamValidator::PARAM_TYPE => 'string'
227 protected function getExamplesMessages() {
228 return [
229 'action=query&list=watchlistraw'
230 => 'apihelp-query+watchlistraw-example-simple',
231 'action=query&generator=watchlistraw&gwrshow=changed&prop=info'
232 => 'apihelp-query+watchlistraw-example-generator',
236 public function getHelpUrls() {
237 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Watchlistraw';
241 /** @deprecated class alias since 1.43 */
242 class_alias( ApiQueryWatchlistRaw::class, 'ApiQueryWatchlistRaw' );