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