MediaWiki  master
ApiFeedContributions.php
Go to the documentation of this file.
1 <?php
29 
34 
36  private $revisionStore;
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(
94  $this->getContext(), [
95  'target' => $target,
96  'namespace' => $params['namespace'],
97  'start' => $params['start'],
98  'end' => $params['end'],
99  'tagFilter' => $params['tagfilter'],
100  'deletedOnly' => $params['deletedonly'],
101  'topOnly' => $params['toponly'],
102  'newOnly' => $params['newonly'],
103  'hideMinor' => $params['hideminor'],
104  'showSizeDiff' => $params['showsizediff'],
105  ],
106  MediaWikiServices::getInstance()->getLinkRenderer(),
107  MediaWikiServices::getInstance()->getLinkBatchFactory()
108  );
109 
110  $feedLimit = $this->getConfig()->get( 'FeedLimit' );
111  if ( $pager->getLimit() > $feedLimit ) {
112  $pager->setLimit( $feedLimit );
113  }
114 
115  $feedItems = [];
116  if ( $pager->getNumRows() > 0 ) {
117  $count = 0;
118  $limit = $pager->getLimit();
119  foreach ( $pager->mResult as $row ) {
120  // ContribsPager selects one more row for navigation, skip that row
121  if ( ++$count > $limit ) {
122  break;
123  }
124  $item = $this->feedItem( $row );
125  if ( $item !== null ) {
126  $feedItems[] = $item;
127  }
128  }
129  }
130 
131  ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems );
132  }
133 
134  protected function feedItem( $row ) {
135  // This hook is the api contributions equivalent to the
136  // ContributionsLineEnding hook. Hook implementers may cancel
137  // the hook to signal the user is not allowed to read this item.
138  $feedItem = null;
139  $hookResult = $this->getHookRunner()->onApiFeedContributions__feedItem(
140  $row, $this->getContext(), $feedItem );
141  // Hook returned a valid feed item
142  if ( $feedItem instanceof FeedItem ) {
143  return $feedItem;
144  // Hook was canceled and did not return a valid feed item
145  } elseif ( !$hookResult ) {
146  return null;
147  }
148 
149  // Hook completed and did not return a valid feed item
150  $title = Title::makeTitle( (int)$row->page_namespace, $row->page_title );
151  $user = $this->getUser();
152 
153  if ( $title && $this->getPermissionManager()->userCan( 'read', $user, $title ) ) {
154  $date = $row->rev_timestamp;
155  $comments = $title->getTalkPage()->getFullURL();
156  $revision = $this->revisionStore->newRevisionFromRow( $row, 0, $title );
157 
158  return new FeedItem(
159  $title->getPrefixedText(),
160  $this->feedItemDesc( $revision ),
161  $title->getFullURL( [ 'diff' => $revision->getId() ] ),
162  $date,
163  $this->feedItemAuthor( $revision ),
164  $comments
165  );
166  }
167 
168  return null;
169  }
170 
176  protected function feedItemAuthor( RevisionRecord $revision ) {
177  $user = $revision->getUser();
178  return $user ? $user->getName() : '';
179  }
180 
186  protected function feedItemDesc( RevisionRecord $revision ) {
187  $msg = wfMessage( 'colon-separator' )->inContentLanguage()->text();
188  try {
189  $content = $revision->getContent( SlotRecord::MAIN );
190  } catch ( RevisionAccessException $e ) {
191  $content = null;
192  }
193 
194  if ( $content instanceof TextContent ) {
195  // only textual content has a "source view".
196  $html = nl2br( htmlspecialchars( $content->getText() ) );
197  } else {
198  // XXX: we could get an HTML representation of the content via getParserOutput, but that may
199  // contain JS magic and generally may not be suitable for inclusion in a feed.
200  // Perhaps Content should have a getDescriptiveHtml method and/or a getSourceText method.
201  // Compare also FeedUtils::formatDiffRow.
202  $html = '';
203  }
204 
205  $comment = $revision->getComment();
206 
207  return '<p>' . htmlspecialchars( $this->feedItemAuthor( $revision ) ) . $msg .
208  htmlspecialchars( FeedItem::stripComment( $comment ? $comment->text : '' ) ) .
209  "</p>\n<hr />\n<div>" . $html . '</div>';
210  }
211 
212  public function getAllowedParams() {
213  $feedFormatNames = array_keys( $this->getConfig()->get( 'FeedClasses' ) );
214 
215  $ret = [
216  'feedformat' => [
217  ApiBase::PARAM_DFLT => 'rss',
218  ApiBase::PARAM_TYPE => $feedFormatNames
219  ],
220  'user' => [
221  ApiBase::PARAM_TYPE => 'user',
222  UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name', 'ip', 'cidr', 'id', 'interwiki' ],
223  ApiBase::PARAM_REQUIRED => true,
224  ],
225  'namespace' => [
226  ApiBase::PARAM_TYPE => 'namespace'
227  ],
228  'year' => [
229  ApiBase::PARAM_TYPE => 'integer'
230  ],
231  'month' => [
232  ApiBase::PARAM_TYPE => 'integer'
233  ],
234  'tagfilter' => [
235  ApiBase::PARAM_ISMULTI => true,
237  ApiBase::PARAM_DFLT => '',
238  ],
239  'deletedonly' => false,
240  'toponly' => false,
241  'newonly' => false,
242  'hideminor' => false,
243  'showsizediff' => [
244  ApiBase::PARAM_DFLT => false,
245  ],
246  ];
247 
248  if ( $this->getConfig()->get( 'MiserMode' ) ) {
249  $ret['showsizediff'][ApiBase::PARAM_HELP_MSG] = 'api-help-param-disabled-in-miser-mode';
250  }
251 
252  return $ret;
253  }
254 
255  protected function getExamplesMessages() {
256  return [
257  'action=feedcontributions&user=Example'
258  => 'apihelp-feedcontributions-example-simple',
259  ];
260  }
261 }
ContextSource\getConfig
getConfig()
Definition: ContextSource.php:67
Revision\RevisionAccessException
Exception representing a failure to look up a revision.
Definition: RevisionAccessException.php:34
FeedItem
A base class for outputting syndication feeds (e.g.
Definition: FeedItem.php:33
ContextSource\getContext
getContext()
Get the base IContextSource object.
Definition: ContextSource.php:42
Revision\RevisionRecord
Page revision base class.
Definition: RevisionRecord.php:46
ApiBase\PARAM_REQUIRED
const PARAM_REQUIRED
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:76
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:158
Revision\RevisionStore
Service for looking up page revisions.
Definition: RevisionStore.php:81
ApiBase\dieWithError
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:1381
ApiBase\PARAM_HELP_MSG
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition: ApiBase.php:106
ApiFeedContributions\getCustomPrinter
getCustomPrinter()
This module uses a custom feed wrapper printer.
Definition: ApiFeedContributions.php:46
ApiBase\PARAM_TYPE
const PARAM_TYPE
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:70
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:564
ApiFeedContributions\execute
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
Definition: ApiFeedContributions.php:50
FeedItem\stripComment
static stripComment( $text)
Quickie hack...
Definition: FeedItem.php:220
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1220
SpecialPage\getTitleFor
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,...
Definition: SpecialPage.php:92
ContextSource\getUser
getUser()
Stable to override.
Definition: ContextSource.php:131
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:52
ContribsPager\processDateFilter
static processDateFilter(array $opts)
Set up date filter options, given request data.
Definition: ContribsPager.php:825
ApiFeedContributions\$titleParser
TitleParser $titleParser
Definition: ApiFeedContributions.php:39
Wikimedia\ParamValidator\ParamValidator::TypeDef\UserDef
Type definition for user types.
Definition: UserDef.php:25
ApiFormatFeedWrapper
This printer is used to wrap an instance of the Feed class.
Definition: ApiFormatFeedWrapper.php:27
Revision\RevisionRecord\getUser
getUser( $audience=self::FOR_PUBLIC, User $user=null)
Fetch revision's author's user identity, if it's available to the specified audience.
Definition: RevisionRecord.php:371
ApiFeedContributions\feedItemAuthor
feedItemAuthor(RevisionRecord $revision)
Definition: ApiFeedContributions.php:176
ApiFeedContributions
Definition: ApiFeedContributions.php:33
ApiBase\extractRequestParams
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:716
ChangeTags\listDefinedTags
static listDefinedTags()
Basically lists defined tags which count even if they aren't applied to anything.
Definition: ChangeTags.php:1483
$title
$title
Definition: testCompression.php:38
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:591
TitleParser
A title parser service for MediaWiki.
Definition: TitleParser.php:33
ApiFeedContributions\$revisionStore
RevisionStore $revisionStore
Definition: ApiFeedContributions.php:36
ContribsPager
Pager for Special:Contributions.
Definition: ContribsPager.php:35
$content
$content
Definition: router.php:76
ApiBase\getPermissionManager
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
Definition: ApiBase.php:636
Revision\RevisionRecord\getComment
getComment( $audience=self::FOR_PUBLIC, User $user=null)
Fetch revision comment, if it's available to the specified audience.
Definition: RevisionRecord.php:396
TextContent
Content object implementation for representing flat text.
Definition: TextContent.php:39
ApiFeedContributions\feedItemDesc
feedItemDesc(RevisionRecord $revision)
Definition: ApiFeedContributions.php:186
ApiBase\PARAM_DFLT
const PARAM_DFLT
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:68
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:69
Revision\RevisionRecord\getContent
getContent( $role, $audience=self::FOR_PUBLIC, User $user=null)
Returns the Content of the given slot of this revision.
Definition: RevisionRecord.php:167
ApiFeedContributions\feedItem
feedItem( $row)
Definition: ApiFeedContributions.php:134
ApiBase\getMain
getMain()
Get the main module.
Definition: ApiBase.php:459
ApiFeedContributions\getAllowedParams
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
Definition: ApiFeedContributions.php:212
ApiFeedContributions\getExamplesMessages
getExamplesMessages()
Returns usage examples for this module.
Definition: ApiFeedContributions.php:255
ApiBase\getHookRunner
getHookRunner()
Get an ApiHookRunner for running core API hooks.
Definition: ApiBase.php:661
ExternalUserNames\isExternal
static isExternal( $username)
Tells whether the username is external or not.
Definition: ExternalUserNames.php:137
ApiFormatFeedWrapper\setResult
static setResult( $result, $feed, $feedItems)
Call this method to initialize output data.
Definition: ApiFormatFeedWrapper.php:39
Revision\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:39