MediaWiki REL1_35
ApiFeedContributions.php
Go to the documentation of this file.
1<?php
29
34
37
39 private $titleParser;
40
46 public function getCustomPrinter() {
47 return new ApiFormatFeedWrapper( $this->getMain() );
48 }
49
50 public function execute() {
51 $this->revisionStore = MediaWikiServices::getInstance()->getRevisionStore();
52 $this->titleParser = MediaWikiServices::getInstance()->getTitleParser();
53
54 $params = $this->extractRequestParams();
55
56 $config = $this->getConfig();
57 if ( !$config->get( 'Feed' ) ) {
58 $this->dieWithError( 'feed-unavailable' );
59 }
60
61 $feedClasses = $config->get( 'FeedClasses' );
62 if ( !isset( $feedClasses[$params['feedformat']] ) ) {
63 $this->dieWithError( 'feed-invalid' );
64 }
65
66 if ( $params['showsizediff'] && $this->getConfig()->get( 'MiserMode' ) ) {
67 $this->dieWithError( 'apierror-sizediffdisabled' );
68 }
69
70 $msg = wfMessage( 'Contributions' )->inContentLanguage()->text();
71 $feedTitle = $config->get( 'Sitename' ) . ' - ' . $msg .
72 ' [' . $config->get( 'LanguageCode' ) . ']';
73
74 $target = $params['user'];
75 if ( ExternalUserNames::isExternal( $target ) ) {
76 // Interwiki names make invalid titles, so put the target in the query instead.
77 $feedUrl = SpecialPage::getTitleFor( 'Contributions' )->getFullURL( [ 'target' => $target ] );
78 } else {
79 $feedUrl = SpecialPage::getTitleFor( 'Contributions', $target )->getFullURL();
80 }
81
82 $feed = new $feedClasses[$params['feedformat']] (
83 $feedTitle,
84 htmlspecialchars( $msg ),
85 $feedUrl
86 );
87
88 // Convert year/month parameters to end parameter
89 $params['start'] = '';
90 $params['end'] = '';
91 $params = ContribsPager::processDateFilter( $params );
92
93 $pager = new ContribsPager( $this->getContext(), [
94 'target' => $target,
95 'namespace' => $params['namespace'],
96 'start' => $params['start'],
97 'end' => $params['end'],
98 'tagFilter' => $params['tagfilter'],
99 'deletedOnly' => $params['deletedonly'],
100 'topOnly' => $params['toponly'],
101 'newOnly' => $params['newonly'],
102 'hideMinor' => $params['hideminor'],
103 'showSizeDiff' => $params['showsizediff'],
104 ] );
105
106 $feedLimit = $this->getConfig()->get( 'FeedLimit' );
107 if ( $pager->getLimit() > $feedLimit ) {
108 $pager->setLimit( $feedLimit );
109 }
110
111 $feedItems = [];
112 if ( $pager->getNumRows() > 0 ) {
113 $count = 0;
114 $limit = $pager->getLimit();
115 foreach ( $pager->mResult as $row ) {
116 // ContribsPager selects one more row for navigation, skip that row
117 if ( ++$count > $limit ) {
118 break;
119 }
120 $item = $this->feedItem( $row );
121 if ( $item !== null ) {
122 $feedItems[] = $item;
123 }
124 }
125 }
126
127 ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems );
128 }
129
130 protected function feedItem( $row ) {
131 // This hook is the api contributions equivalent to the
132 // ContributionsLineEnding hook. Hook implementers may cancel
133 // the hook to signal the user is not allowed to read this item.
134 $feedItem = null;
135 $hookResult = $this->getHookRunner()->onApiFeedContributions__feedItem(
136 $row, $this->getContext(), $feedItem );
137 // Hook returned a valid feed item
138 if ( $feedItem instanceof FeedItem ) {
139 return $feedItem;
140 // Hook was canceled and did not return a valid feed item
141 } elseif ( !$hookResult ) {
142 return null;
143 }
144
145 // Hook completed and did not return a valid feed item
146 $title = Title::makeTitle( (int)$row->page_namespace, $row->page_title );
147 $user = $this->getUser();
148
149 if ( $title && $this->getPermissionManager()->userCan( 'read', $user, $title ) ) {
150 $date = $row->rev_timestamp;
151 $comments = $title->getTalkPage()->getFullURL();
152 $revision = $this->revisionStore->newRevisionFromRow( $row, 0, $title );
153
154 return new FeedItem(
155 $title->getPrefixedText(),
156 $this->feedItemDesc( $revision ),
157 $title->getFullURL( [ 'diff' => $revision->getId() ] ),
158 $date,
159 $this->feedItemAuthor( $revision ),
160 $comments
161 );
162 }
163
164 return null;
165 }
166
172 protected function feedItemAuthor( RevisionRecord $revision ) {
173 $user = $revision->getUser();
174 return $user ? $user->getName() : '';
175 }
176
182 protected function feedItemDesc( RevisionRecord $revision ) {
183 $msg = wfMessage( 'colon-separator' )->inContentLanguage()->text();
184 try {
185 $content = $revision->getContent( SlotRecord::MAIN );
186 } catch ( RevisionAccessException $e ) {
187 $content = null;
188 }
189
190 if ( $content instanceof TextContent ) {
191 // only textual content has a "source view".
192 $html = nl2br( htmlspecialchars( $content->getText() ) );
193 } else {
194 // XXX: we could get an HTML representation of the content via getParserOutput, but that may
195 // contain JS magic and generally may not be suitable for inclusion in a feed.
196 // Perhaps Content should have a getDescriptiveHtml method and/or a getSourceText method.
197 // Compare also FeedUtils::formatDiffRow.
198 $html = '';
199 }
200
201 $comment = $revision->getComment();
202
203 return '<p>' . htmlspecialchars( $this->feedItemAuthor( $revision ) ) . $msg .
204 htmlspecialchars( FeedItem::stripComment( $comment ? $comment->text : '' ) ) .
205 "</p>\n<hr />\n<div>" . $html . '</div>';
206 }
207
208 public function getAllowedParams() {
209 $feedFormatNames = array_keys( $this->getConfig()->get( 'FeedClasses' ) );
210
211 $ret = [
212 'feedformat' => [
213 ApiBase::PARAM_DFLT => 'rss',
214 ApiBase::PARAM_TYPE => $feedFormatNames
215 ],
216 'user' => [
217 ApiBase::PARAM_TYPE => 'user',
218 UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name', 'ip', 'cidr', 'id', 'interwiki' ],
220 ],
221 'namespace' => [
222 ApiBase::PARAM_TYPE => 'namespace'
223 ],
224 'year' => [
225 ApiBase::PARAM_TYPE => 'integer'
226 ],
227 'month' => [
228 ApiBase::PARAM_TYPE => 'integer'
229 ],
230 'tagfilter' => [
234 ],
235 'deletedonly' => false,
236 'toponly' => false,
237 'newonly' => false,
238 'hideminor' => false,
239 'showsizediff' => [
240 ApiBase::PARAM_DFLT => false,
241 ],
242 ];
243
244 if ( $this->getConfig()->get( 'MiserMode' ) ) {
245 $ret['showsizediff'][ApiBase::PARAM_HELP_MSG] = 'api-help-param-disabled-in-miser-mode';
246 }
247
248 return $ret;
249 }
250
251 protected function getExamplesMessages() {
252 return [
253 'action=feedcontributions&user=Example'
254 => 'apihelp-feedcontributions-example-simple',
255 ];
256 }
257}
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:52
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
Definition ApiBase.php:1437
const PARAM_REQUIRED
Definition ApiBase.php:102
getMain()
Get the main module.
Definition ApiBase.php:515
const PARAM_TYPE
Definition ApiBase.php:78
const PARAM_DFLT
Definition ApiBase.php:70
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
Definition ApiBase.php:692
getResult()
Get the result object.
Definition ApiBase.php:620
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:772
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition ApiBase.php:162
getHookRunner()
Get an ApiHookRunner for running core API hooks.
Definition ApiBase.php:717
const PARAM_ISMULTI
Definition ApiBase.php:74
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.
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.
static listDefinedTags()
Basically lists defined tags which count even if they aren't applied to anything.
getUser()
Stable to override.
getContext()
Get the base IContextSource object.
A base class for outputting syndication feeds (e.g.
Definition FeedItem.php:33
MediaWikiServices is the service locator for the application scope of MediaWiki.
Type definition for user types.
Definition UserDef.php:23
Exception representing a failure to look up a revision.
Page revision base class.
getComment( $audience=self::FOR_PUBLIC, User $user=null)
Fetch revision comment, if it's available to the specified audience.
getContent( $role, $audience=self::FOR_PUBLIC, User $user=null)
Returns the Content of the given slot of this revision.
getUser( $audience=self::FOR_PUBLIC, User $user=null)
Fetch revision's author's user identity, if it's available to the specified audience.
Service for looking up page revisions.
Value object representing a content slot associated with a page revision.
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.
$content
Definition router.php:76