specialPageFactory = $specialPageFactory; $this->tempUserConfig = $tempUserConfig; } /** * This module uses a custom feed wrapper printer. * * @return ApiFormatFeedWrapper */ public function getCustomPrinter() { return new ApiFormatFeedWrapper( $this->getMain() ); } /** * Format the rows (generated by SpecialRecentchanges or SpecialRecentchangeslinked) * as an RSS/Atom feed. */ public function execute() { $config = $this->getConfig(); $this->params = $this->extractRequestParams(); if ( !$config->get( MainConfigNames::Feed ) ) { $this->dieWithError( 'feed-unavailable' ); } $feedClasses = $config->get( MainConfigNames::FeedClasses ); if ( !isset( $feedClasses[$this->params['feedformat']] ) ) { $this->dieWithError( 'feed-invalid' ); } $this->getMain()->setCacheMode( 'public' ); if ( !$this->getMain()->getParameter( 'smaxage' ) ) { // T65249: This page gets hit a lot, cache at least 15 seconds. $this->getMain()->setCacheMaxAge( 15 ); } $feedFormat = $this->params['feedformat']; $specialPageName = $this->params['target'] !== null ? 'Recentchangeslinked' : 'Recentchanges'; $formatter = $this->getFeedObject( $feedFormat, $specialPageName ); // Parameters are passed via the request in the context… :( $context = new DerivativeContext( $this ); $context->setRequest( new DerivativeRequest( $this->getRequest(), $this->params, $this->getRequest()->wasPosted() ) ); // The row-getting functionality should be factored out of ChangesListSpecialPage too… $rc = $this->specialPageFactory->getPage( $specialPageName ); if ( $rc === null ) { throw new RuntimeException( __METHOD__ . ' not able to instance special page ' . $specialPageName ); } '@phan-var \MediaWiki\SpecialPage\ChangesListSpecialPage $rc'; $rc->setContext( $context ); $rows = $rc->getRows(); $feedItems = $rows ? ChangesFeed::buildItems( $rows ) : []; ApiFormatFeedWrapper::setResult( $this->getResult(), $formatter, $feedItems ); } /** * Return a MediaWiki\Feed\ChannelFeed object. * * @param string $feedFormat Feed's format (either 'rss' or 'atom') * @param string $specialPageName Relevant special page name (either 'Recentchanges' or * 'Recentchangeslinked') * @return ChannelFeed */ private function getFeedObject( $feedFormat, $specialPageName ) { if ( $specialPageName === 'Recentchangeslinked' ) { $title = Title::newFromText( $this->params['target'] ); if ( !$title || $title->isExternal() ) { $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $this->params['target'] ) ] ); } $feed = new ChangesFeed( $feedFormat ); $feedObj = $feed->getFeedObject( $this->msg( 'recentchangeslinked-title', $title->getPrefixedText() ) ->inContentLanguage()->text(), $this->msg( 'recentchangeslinked-feed' )->inContentLanguage()->text(), SpecialPage::getTitleFor( 'Recentchangeslinked' )->getFullURL() ); } else { $feed = new ChangesFeed( $feedFormat ); $feedObj = $feed->getFeedObject( $this->msg( 'recentchanges' )->inContentLanguage()->text(), $this->msg( 'recentchanges-feed-description' )->inContentLanguage()->text(), SpecialPage::getTitleFor( 'Recentchanges' )->getFullURL() ); } return $feedObj; } public function getAllowedParams() { $config = $this->getConfig(); $feedFormatNames = array_keys( $config->get( MainConfigNames::FeedClasses ) ); return [ 'feedformat' => [ ParamValidator::PARAM_DEFAULT => 'rss', ParamValidator::PARAM_TYPE => $feedFormatNames, ], 'namespace' => [ ParamValidator::PARAM_TYPE => 'namespace', ], // TODO: Rename this option to 'invertnamespaces'? 'invert' => false, 'associated' => false, 'days' => [ ParamValidator::PARAM_DEFAULT => 7, IntegerDef::PARAM_MIN => 1, ParamValidator::PARAM_TYPE => 'integer', ], 'limit' => [ ParamValidator::PARAM_DEFAULT => 50, IntegerDef::PARAM_MIN => 1, IntegerDef::PARAM_MAX => $config->get( MainConfigNames::FeedLimit ), ParamValidator::PARAM_TYPE => 'integer', ], 'from' => [ ParamValidator::PARAM_TYPE => 'timestamp', ], 'hideminor' => false, 'hidebots' => false, 'hideanons' => [ ParamValidator::PARAM_DEFAULT => false, ApiBase::PARAM_HELP_MSG => $this->tempUserConfig->isEnabled() ? 'apihelp-feedrecentchanges-param-hideanons-temp' : 'apihelp-feedrecentchanges-param-hideanons', ], 'hideliu' => false, 'hidepatrolled' => false, 'hidemyself' => false, 'hidecategorization' => false, 'tagfilter' => [ ParamValidator::PARAM_TYPE => 'string', ], 'inverttags' => false, 'target' => [ ParamValidator::PARAM_TYPE => 'string', ], 'showlinkedto' => false, ]; } protected function getExamplesMessages() { return [ 'action=feedrecentchanges' => 'apihelp-feedrecentchanges-example-simple', 'action=feedrecentchanges&days=30' => 'apihelp-feedrecentchanges-example-30days', ]; } public function getHelpUrls() { return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Feedrecentchanges'; } }