MediaWiki REL1_39
FeedUtils.php
Go to the documentation of this file.
1<?php
28
34class FeedUtils {
35
45 public static function checkFeedOutput( $type, $output = null ) {
46 $feed = MediaWikiServices::getInstance()->getMainConfig()->get( MainConfigNames::Feed );
47 $feedClasses = MediaWikiServices::getInstance()->getMainConfig()->get( MainConfigNames::FeedClasses );
48 if ( $output === null ) {
49 // Todo update GoogleNewsSitemap and deprecate
50 global $wgOut;
51 $output = $wgOut;
52 }
53
54 if ( !$feed ) {
55 $output->addWikiMsg( 'feed-unavailable' );
56 return false;
57 }
58
59 if ( !isset( $feedClasses[$type] ) ) {
60 $output->addWikiMsg( 'feed-invalid' );
61 return false;
62 }
63
64 return true;
65 }
66
76 public static function formatDiff( $row, $formattedComment = null ) {
77 $titleObj = Title::makeTitle( $row->rc_namespace, $row->rc_title );
78 $timestamp = wfTimestamp( TS_MW, $row->rc_timestamp );
79 $actiontext = '';
80 if ( $row->rc_type == RC_LOG ) {
81 $rcRow = (array)$row; // newFromRow() only accepts arrays for RC rows
82 $actiontext = LogFormatter::newFromRow( $rcRow )->getActionText();
83 }
84 if ( $row->rc_deleted & RevisionRecord::DELETED_COMMENT ) {
85 $formattedComment = wfMessage( 'rev-deleted-comment' )->escaped();
86 } elseif ( $formattedComment === null ) {
87 $formattedComment = Linker::formatComment(
88 CommentStore::getStore()->getComment( 'rc_comment', $row )->text );
89 }
90 return self::formatDiffRow2( $titleObj,
91 $row->rc_last_oldid, $row->rc_this_oldid,
92 $timestamp,
93 $formattedComment,
94 $actiontext
95 );
96 }
97
111 public static function formatDiffRow( $title, $oldid, $newid, $timestamp,
112 $comment, $actiontext = ''
113 ) {
114 $formattedComment = MediaWikiServices::getInstance()->getCommentFormatter()
115 ->format( $comment );
116 return self::formatDiffRow2( $title, $oldid, $newid, $timestamp,
117 $formattedComment, $actiontext );
118 }
119
132 public static function formatDiffRow2( $title, $oldid, $newid, $timestamp,
133 $formattedComment, $actiontext = ''
134 ) {
135 $feedDiffCutoff = MediaWikiServices::getInstance()->getMainConfig()->get( MainConfigNames::FeedDiffCutoff );
136
137 // log entries
138 $unwrappedText = implode(
139 ' ',
140 array_filter( [ $actiontext, $formattedComment ] )
141 );
142 $completeText = Html::rawElement( 'p', [], $unwrappedText ) . "\n";
143
144 // NOTE: Check permissions for anonymous users, not current user.
145 // No "privileged" version should end up in the cache.
146 // Most feed readers will not log in anyway.
147 $anon = new User();
148 $services = MediaWikiServices::getInstance();
149 $permManager = $services->getPermissionManager();
150 $accErrors = $permManager->getPermissionErrors(
151 'read',
152 $anon,
153 $title
154 );
155
156 // Can't diff special pages, unreadable pages or pages with no new revision
157 // to compare against: just return the text.
158 if ( $title->getNamespace() < 0 || $accErrors || !$newid ) {
159 return $completeText;
160 }
161
162 $revLookup = $services->getRevisionLookup();
163 $contentHandlerFactory = $services->getContentHandlerFactory();
164 if ( $oldid ) {
165 $diffText = '';
166 // Don't bother generating the diff if we won't be able to show it
167 if ( $feedDiffCutoff > 0 ) {
168 $revRecord = $revLookup->getRevisionById( $oldid );
169
170 if ( !$revRecord ) {
171 $diffText = false;
172 } else {
173 $mainContext = RequestContext::getMain();
174 $context = clone RequestContext::getMain();
175 $context->setTitle( $title );
176
177 $model = $revRecord->getSlot(
178 SlotRecord::MAIN,
179 RevisionRecord::RAW
180 )->getModel();
181 $contentHandler = $contentHandlerFactory->getContentHandler( $model );
182 $de = $contentHandler->createDifferenceEngine( $context, $oldid, $newid );
183 $lang = $mainContext->getLanguage();
184 $user = $mainContext->getUser();
185 $diffText = $de->getDiff(
186 $mainContext->msg( 'previousrevision' )->text(), // hack
187 $mainContext->msg( 'revisionasof',
188 $lang->userTimeAndDate( $timestamp, $user ),
189 $lang->userDate( $timestamp, $user ),
190 $lang->userTime( $timestamp, $user ) )->text() );
191 }
192 }
193
194 if ( $feedDiffCutoff <= 0 || ( strlen( $diffText ) > $feedDiffCutoff ) ) {
195 // Omit large diffs
196 $diffText = self::getDiffLink( $title, $newid, $oldid );
197 } elseif ( $diffText === false ) {
198 // Error in diff engine, probably a missing revision
199 $diffText = Html::rawElement(
200 'p',
201 [],
202 "Can't load revision $newid"
203 );
204 } else {
205 // Diff output fine, clean up any illegal UTF-8
206 $diffText = UtfNormal\Validator::cleanUp( $diffText );
207 $diffText = self::applyDiffStyle( $diffText );
208 }
209 } else {
210 $revRecord = $revLookup->getRevisionById( $newid );
211 if ( $feedDiffCutoff <= 0 || $revRecord === null ) {
212 $newContent = $contentHandlerFactory
213 ->getContentHandler( $title->getContentModel() )
214 ->makeEmptyContent();
215 } else {
216 $newContent = $revRecord->getContent( SlotRecord::MAIN );
217 }
218
219 if ( $newContent instanceof TextContent ) {
220 // only textual content has a "source view".
221 $text = $newContent->getText();
222
223 if ( $feedDiffCutoff <= 0 || strlen( $text ) > $feedDiffCutoff ) {
224 $html = null;
225 } else {
226 $html = nl2br( htmlspecialchars( $text ) );
227 }
228 } else {
229 // XXX: we could get an HTML representation of the content via getParserOutput, but that may
230 // contain JS magic and generally may not be suitable for inclusion in a feed.
231 // Perhaps Content should have a getDescriptiveHtml method and/or a getSourceText method.
232 // Compare also ApiFeedContributions::feedItemDesc
233 $html = null;
234 }
235
236 if ( $html === null ) {
237 // Omit large new page diffs, T31110
238 // Also use diff link for non-textual content
239 $diffText = self::getDiffLink( $title, $newid );
240 } else {
241 $diffText = Html::rawElement(
242 'p',
243 [],
244 Html::rawElement( 'b', [], wfMessage( 'newpage' )->text() )
245 );
246 $diffText .= Html::rawElement( 'div', [], $html );
247 }
248 }
249 $completeText .= $diffText;
250
251 return $completeText;
252 }
253
263 protected static function getDiffLink( Title $title, $newid, $oldid = null ) {
264 $queryParameters = [ 'diff' => $newid ];
265 if ( $oldid != null ) {
266 $queryParameters['oldid'] = $oldid;
267 }
268 $diffUrl = $title->getFullURL( $queryParameters );
269
270 $diffLink = Html::element( 'a', [ 'href' => $diffUrl ],
271 wfMessage( 'showdiff' )->inContentLanguage()->text() );
272
273 return $diffLink;
274 }
275
284 public static function applyDiffStyle( $text ) {
285 $styles = [
286 'diff' => 'background-color: #fff; color: #202122;',
287 'diff-otitle' => 'background-color: #fff; color: #202122; text-align: center;',
288 'diff-ntitle' => 'background-color: #fff; color: #202122; text-align: center;',
289 'diff-addedline' => 'color: #202122; font-size: 88%; border-style: solid; '
290 . 'border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; '
291 . 'vertical-align: top; white-space: pre-wrap;',
292 'diff-deletedline' => 'color: #202122; font-size: 88%; border-style: solid; '
293 . 'border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; '
294 . 'vertical-align: top; white-space: pre-wrap;',
295 'diff-context' => 'background-color: #f8f9fa; color: #202122; font-size: 88%; '
296 . 'border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; '
297 . 'border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;',
298 'diffchange' => 'font-weight: bold; text-decoration: none;',
299 ];
300
301 foreach ( $styles as $class => $style ) {
302 $text = preg_replace( '/(<\w+\b[^<>]*)\bclass=([\'"])(?:[^\'"]*\s)?' .
303 preg_quote( $class ) . '(?:\s[^\'"]*)?\2(?=[^<>]*>)/',
304 '$1style="' . $style . '"', $text );
305 }
306
307 return $text;
308 }
309
310}
const RC_LOG
Definition Defines.php:118
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
if(!defined( 'MW_NO_SESSION') &&! $wgCommandLineMode $wgOut
Definition Setup.php:497
Helper functions for feeds.
Definition FeedUtils.php:34
static formatDiffRow( $title, $oldid, $newid, $timestamp, $comment, $actiontext='')
Really format a diff for the newsfeed.
static formatDiffRow2( $title, $oldid, $newid, $timestamp, $formattedComment, $actiontext='')
Really really format a diff for the newsfeed.
static formatDiff( $row, $formattedComment=null)
Format a diff for the newsfeed.
Definition FeedUtils.php:76
static applyDiffStyle( $text)
Hacky application of diff styles for the feeds.
static getDiffLink(Title $title, $newid, $oldid=null)
Generates a diff link.
static checkFeedOutput( $type, $output=null)
Check whether feeds can be used and that $type is a valid feed type.
Definition FeedUtils.php:45
static formatComment( $comment, $title=null, $local=false, $wikiId=null)
This function is called by all recent changes variants, by the page history, and by the user contribu...
Definition Linker.php:1449
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
Page revision base class.
Value object representing a content slot associated with a page revision.
Content object implementation for representing flat text.
Represents a title within MediaWiki.
Definition Title.php:49
internal since 1.36
Definition User.php:70
if(!isset( $args[0])) $lang