MediaWiki REL1_37
ApiFeedContributions.php
Go to the documentation of this file.
1<?php
34
39
42
44 private $titleParser;
45
48
51
54
57
60
63
65 private $userFactory;
66
68 private $hookRunner;
69
83 public function __construct(
84 ApiMain $main,
85 $action,
95 ) {
96 parent::__construct( $main, $action );
97 $this->revisionStore = $revisionStore;
98 $this->titleParser = $titleParser;
99 $this->linkRenderer = $linkRenderer;
100 $this->linkBatchFactory = $linkBatchFactory;
101 $this->hookContainer = $hookContainer;
102 $this->loadBalancer = $loadBalancer;
103 $this->namespaceInfo = $namespaceInfo;
104 $this->actorMigration = $actorMigration;
105 $this->userFactory = $userFactory;
106
107 $this->hookRunner = new ApiHookRunner( $hookContainer );
108 }
109
115 public function getCustomPrinter() {
116 return new ApiFormatFeedWrapper( $this->getMain() );
117 }
118
119 public function execute() {
120 $params = $this->extractRequestParams();
121
122 $config = $this->getConfig();
123 if ( !$config->get( 'Feed' ) ) {
124 $this->dieWithError( 'feed-unavailable' );
125 }
126
127 $feedClasses = $config->get( 'FeedClasses' );
128 if ( !isset( $feedClasses[$params['feedformat']] ) ) {
129 $this->dieWithError( 'feed-invalid' );
130 }
131
132 if ( $params['showsizediff'] && $this->getConfig()->get( 'MiserMode' ) ) {
133 $this->dieWithError( 'apierror-sizediffdisabled' );
134 }
135
136 $msg = wfMessage( 'Contributions' )->inContentLanguage()->text();
137 $feedTitle = $config->get( 'Sitename' ) . ' - ' . $msg .
138 ' [' . $config->get( 'LanguageCode' ) . ']';
139
140 $target = $params['user'];
141 if ( ExternalUserNames::isExternal( $target ) ) {
142 // Interwiki names make invalid titles, so put the target in the query instead.
143 $feedUrl = SpecialPage::getTitleFor( 'Contributions' )->getFullURL( [ 'target' => $target ] );
144 } else {
145 $feedUrl = SpecialPage::getTitleFor( 'Contributions', $target )->getFullURL();
146 }
147
148 $feed = new $feedClasses[$params['feedformat']] (
149 $feedTitle,
150 htmlspecialchars( $msg ),
151 $feedUrl
152 );
153
154 // Convert year/month parameters to end parameter
155 $params['start'] = '';
156 $params['end'] = '';
157 $params = ContribsPager::processDateFilter( $params );
158
159 $targetUser = $this->userFactory->newFromName( $target, UserFactory::RIGOR_NONE );
160
161 $pager = new ContribsPager(
162 $this->getContext(), [
163 'target' => $target,
164 'namespace' => $params['namespace'],
165 'start' => $params['start'],
166 'end' => $params['end'],
167 'tagFilter' => $params['tagfilter'],
168 'deletedOnly' => $params['deletedonly'],
169 'topOnly' => $params['toponly'],
170 'newOnly' => $params['newonly'],
171 'hideMinor' => $params['hideminor'],
172 'showSizeDiff' => $params['showsizediff'],
173 ],
174 $this->linkRenderer,
175 $this->linkBatchFactory,
176 $this->hookContainer,
177 $this->loadBalancer,
178 $this->actorMigration,
179 $this->revisionStore,
180 $this->namespaceInfo,
181 $targetUser
182 );
183
184 $feedLimit = $this->getConfig()->get( 'FeedLimit' );
185 if ( $pager->getLimit() > $feedLimit ) {
186 $pager->setLimit( $feedLimit );
187 }
188
189 $feedItems = [];
190 if ( $pager->getNumRows() > 0 ) {
191 $count = 0;
192 $limit = $pager->getLimit();
193 foreach ( $pager->mResult as $row ) {
194 // ContribsPager selects one more row for navigation, skip that row
195 if ( ++$count > $limit ) {
196 break;
197 }
198 $item = $this->feedItem( $row );
199 if ( $item !== null ) {
200 $feedItems[] = $item;
201 }
202 }
203 }
204
205 ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems );
206 }
207
208 protected function feedItem( $row ) {
209 // This hook is the api contributions equivalent to the
210 // ContributionsLineEnding hook. Hook implementers may cancel
211 // the hook to signal the user is not allowed to read this item.
212 $feedItem = null;
213 $hookResult = $this->hookRunner->onApiFeedContributions__feedItem(
214 $row, $this->getContext(), $feedItem );
215 // Hook returned a valid feed item
216 if ( $feedItem instanceof FeedItem ) {
217 return $feedItem;
218 // Hook was canceled and did not return a valid feed item
219 } elseif ( !$hookResult ) {
220 return null;
221 }
222
223 // Hook completed and did not return a valid feed item
224 $title = Title::makeTitle( (int)$row->page_namespace, $row->page_title );
225
226 if ( $title && $this->getAuthority()->authorizeRead( 'read', $title ) ) {
227 $date = $row->rev_timestamp;
228 $comments = $title->getTalkPage()->getFullURL();
229 $revision = $this->revisionStore->newRevisionFromRow( $row, 0, $title );
230
231 return new FeedItem(
232 $title->getPrefixedText(),
233 $this->feedItemDesc( $revision ),
234 $title->getFullURL( [ 'diff' => $revision->getId() ] ),
235 $date,
236 $this->feedItemAuthor( $revision ),
237 $comments
238 );
239 }
240
241 return null;
242 }
243
249 protected function feedItemAuthor( RevisionRecord $revision ) {
250 $user = $revision->getUser();
251 return $user ? $user->getName() : '';
252 }
253
259 protected function feedItemDesc( RevisionRecord $revision ) {
260 $msg = wfMessage( 'colon-separator' )->inContentLanguage()->text();
261 try {
262 $content = $revision->getContent( SlotRecord::MAIN );
263 } catch ( RevisionAccessException $e ) {
264 $content = null;
265 }
266
267 if ( $content instanceof TextContent ) {
268 // only textual content has a "source view".
269 $html = nl2br( htmlspecialchars( $content->getText() ) );
270 } else {
271 // XXX: we could get an HTML representation of the content via getParserOutput, but that may
272 // contain JS magic and generally may not be suitable for inclusion in a feed.
273 // Perhaps Content should have a getDescriptiveHtml method and/or a getSourceText method.
274 // Compare also FeedUtils::formatDiffRow.
275 $html = '';
276 }
277
278 $comment = $revision->getComment();
279
280 return '<p>' . htmlspecialchars( $this->feedItemAuthor( $revision ) ) . $msg .
281 htmlspecialchars( FeedItem::stripComment( $comment ? $comment->text : '' ) ) .
282 "</p>\n<hr />\n<div>" . $html . '</div>';
283 }
284
285 public function getAllowedParams() {
286 $feedFormatNames = array_keys( $this->getConfig()->get( 'FeedClasses' ) );
287
288 $ret = [
289 'feedformat' => [
290 ApiBase::PARAM_DFLT => 'rss',
291 ApiBase::PARAM_TYPE => $feedFormatNames
292 ],
293 'user' => [
294 ApiBase::PARAM_TYPE => 'user',
295 UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name', 'ip', 'cidr', 'id', 'interwiki' ],
297 ],
298 'namespace' => [
299 ApiBase::PARAM_TYPE => 'namespace'
300 ],
301 'year' => [
302 ApiBase::PARAM_TYPE => 'integer'
303 ],
304 'month' => [
305 ApiBase::PARAM_TYPE => 'integer'
306 ],
307 'tagfilter' => [
311 ],
312 'deletedonly' => false,
313 'toponly' => false,
314 'newonly' => false,
315 'hideminor' => false,
316 'showsizediff' => [
317 ApiBase::PARAM_DFLT => false,
318 ],
319 ];
320
321 if ( $this->getConfig()->get( 'MiserMode' ) ) {
322 $ret['showsizediff'][ApiBase::PARAM_HELP_MSG] = 'api-help-param-disabled-in-miser-mode';
323 }
324
325 return $ret;
326 }
327
328 protected function getExamplesMessages() {
329 return [
330 'action=feedcontributions&user=Example'
331 => 'apihelp-feedcontributions-example-simple',
332 ];
333 }
334}
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
This is not intended to be a long-term part of MediaWiki; it will be deprecated and removed once acto...
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:55
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
Definition ApiBase.php:1436
const PARAM_REQUIRED
Definition ApiBase.php:105
getMain()
Get the main module.
Definition ApiBase.php:513
const PARAM_TYPE
Definition ApiBase.php:81
const PARAM_DFLT
Definition ApiBase.php:73
getResult()
Get the result object.
Definition ApiBase.php:628
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:764
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition ApiBase.php:162
const PARAM_ISMULTI
Definition ApiBase.php:77
feedItemDesc(RevisionRecord $revision)
feedItemAuthor(RevisionRecord $revision)
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
getCustomPrinter()
This module uses a custom feed wrapper printer.
__construct(ApiMain $main, $action, RevisionStore $revisionStore, TitleParser $titleParser, LinkRenderer $linkRenderer, LinkBatchFactory $linkBatchFactory, HookContainer $hookContainer, ILoadBalancer $loadBalancer, NamespaceInfo $namespaceInfo, ActorMigration $actorMigration, UserFactory $userFactory)
LinkBatchFactory $linkBatchFactory
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
getExamplesMessages()
Returns usage examples for this module.
This printer is used to wrap an instance of the Feed class.
static setResult( $result, $feed, $feedItems)
Call this method to initialize output data.
This is the main API class, used for both external and internal processing.
Definition ApiMain.php:49
static listDefinedTags()
Basically lists defined tags which count even if they aren't applied to anything.
getContext()
Get the base IContextSource object.
Pager for Special:Contributions.
A base class for outputting syndication feeds (e.g.
Definition FeedItem.php:33
This class provides an implementation of the hook interfaces used by the core Action API,...
Class that generates HTML links for pages.
Type definition for user types.
Definition UserDef.php:25
Exception representing a failure to look up a revision.
Page revision base class.
getUser( $audience=self::FOR_PUBLIC, Authority $performer=null)
Fetch revision's author's user identity, if it's available to the specified audience.
getComment( $audience=self::FOR_PUBLIC, Authority $performer=null)
Fetch revision comment, if it's available to the specified audience.
getContent( $role, $audience=self::FOR_PUBLIC, Authority $performer=null)
Returns the Content of the given slot of this revision.
Service for looking up page revisions.
Value object representing a content slot associated with a page revision.
Creates User objects.
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
Content object implementation for representing flat text.
A title parser service for MediaWiki.
Database cluster connection, tracking, load balancing, and transaction manager interface.
$content
Definition router.php:76