1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
<?php
/**
* Helper functions for feeds
*
* @ingroup Feed
*/
class FeedUtils {
/**
* Check whether feed's cache should be cleared; for changes feeds
* If the feed should be purged; $timekey and $key will be removed from
* $messageMemc
*
* @param $timekey String: cache key of the timestamp of the last item
* @param $key String: cache key of feed's content
*/
public static function checkPurge( $timekey, $key ) {
global $wgRequest, $wgUser, $messageMemc;
$purge = $wgRequest->getVal( 'action' ) === 'purge';
if ( $purge && $wgUser->isAllowed('purge') ) {
$messageMemc->delete( $timekey );
$messageMemc->delete( $key );
}
}
/**
* Check whether feeds can be used and that $type is a valid feed type
*
* @param $type String: feed type, as requested by the user
* @return Boolean
*/
public static function checkFeedOutput( $type ) {
global $wgOut, $wgFeed, $wgFeedClasses;
if ( !$wgFeed ) {
$wgOut->addWikiMsg( 'feed-unavailable' );
return false;
}
if( !isset( $wgFeedClasses[$type] ) ) {
$wgOut->addWikiMsg( 'feed-invalid' );
return false;
}
return true;
}
/**
* Format a diff for the newsfeed
*
* @param $row Object: row from the recentchanges table
* @return String
*/
public static function formatDiff( $row ) {
$titleObj = Title::makeTitle( $row->rc_namespace, $row->rc_title );
$timestamp = wfTimestamp( TS_MW, $row->rc_timestamp );
$actiontext = '';
if( $row->rc_type == RC_LOG ) {
$rcRow = (array)$row; // newFromRow() only accepts arrays for RC rows
$actiontext = LogFormatter::newFromRow( $rcRow )->getActionText();
}
return self::formatDiffRow( $titleObj,
$row->rc_last_oldid, $row->rc_this_oldid,
$timestamp,
($row->rc_deleted & Revision::DELETED_COMMENT)
? wfMsgHtml('rev-deleted-comment')
: $row->rc_comment,
$actiontext
);
}
/**
* Really format a diff for the newsfeed
*
* @param $title Title object
* @param $oldid Integer: old revision's id
* @param $newid Integer: new revision's id
* @param $timestamp Integer: new revision's timestamp
* @param $comment String: new revision's comment
* @param $actiontext String: text of the action; in case of log event
* @return String
*/
public static function formatDiffRow( $title, $oldid, $newid, $timestamp, $comment, $actiontext='' ) {
global $wgFeedDiffCutoff, $wgLang;
wfProfileIn( __METHOD__ );
# log enties
$completeText = '<p>' . implode( ' ',
array_filter(
array(
$actiontext,
Linker::formatComment( $comment ) ) ) ) . "</p>\n";
// NOTE: Check permissions for anonymous users, not current user.
// No "privileged" version should end up in the cache.
// Most feed readers will not log in anway.
$anon = new User();
$accErrors = $title->getUserPermissionsErrors( 'read', $anon, true );
// Can't diff special pages, unreadable pages or pages with no new revision
// to compare against: just return the text.
if( $title->getNamespace() < 0 || $accErrors || !$newid ) {
wfProfileOut( __METHOD__ );
return $completeText;
}
if( $oldid ) {
wfProfileIn( __METHOD__."-dodiff" );
#$diffText = $de->getDiff( wfMsg( 'revisionasof',
# $wgLang->timeanddate( $timestamp ),
# $wgLang->date( $timestamp ),
# $wgLang->time( $timestamp ) ),
# wfMsg( 'currentrev' ) );
// Don't bother generating the diff if we won't be able to show it
if ( $wgFeedDiffCutoff > 0 ) {
$de = new DifferenceEngine( $title, $oldid, $newid );
$diffText = $de->getDiff(
wfMsg( 'previousrevision' ), // hack
wfMsg( 'revisionasof',
$wgLang->timeanddate( $timestamp ),
$wgLang->date( $timestamp ),
$wgLang->time( $timestamp ) ) );
}
if ( $wgFeedDiffCutoff <= 0 || ( strlen( $diffText ) > $wgFeedDiffCutoff ) ) {
// Omit large diffs
$diffText = self::getDiffLink( $title, $newid, $oldid );
} elseif ( $diffText === false ) {
// Error in diff engine, probably a missing revision
$diffText = "<p>Can't load revision $newid</p>";
} else {
// Diff output fine, clean up any illegal UTF-8
$diffText = UtfNormal::cleanUp( $diffText );
$diffText = self::applyDiffStyle( $diffText );
}
wfProfileOut( __METHOD__."-dodiff" );
} else {
$rev = Revision::newFromId( $newid );
if( $wgFeedDiffCutoff <= 0 || is_null( $rev ) ) {
$newtext = '';
} else {
$newtext = $rev->getText();
}
if ( $wgFeedDiffCutoff <= 0 || strlen( $newtext ) > $wgFeedDiffCutoff ) {
// Omit large new page diffs, bug 29110
$diffText = self::getDiffLink( $title, $newid );
} else {
$diffText = '<p><b>' . wfMsg( 'newpage' ) . '</b></p>' .
'<div>' . nl2br( htmlspecialchars( $newtext ) ) . '</div>';
}
}
$completeText .= $diffText;
wfProfileOut( __METHOD__ );
return $completeText;
}
/**
* Generates a diff link. Used when the full diff is not wanted for example
* when $wgFeedDiffCutoff is 0.
*
* @param $title Title object: used to generate the diff URL
* @param $newid Integer newid for this diff
* @param $oldid Integer|null oldid for the diff. Null means it is a new article
*/
protected static function getDiffLink( Title $title, $newid, $oldid = null ) {
$queryParameters = ($oldid == null)
? "diff={$newid}"
: "diff={$newid}&oldid={$oldid}" ;
$diffUrl = $title->getFullUrl( $queryParameters );
$diffLink = Html::element( 'a', array( 'href' => $diffUrl ),
wfMsgForContent( 'showdiff' ) );
return $diffLink;
}
/**
* Hacky application of diff styles for the feeds.
* Might be 'cleaner' to use DOM or XSLT or something,
* but *gack* it's a pain in the ass.
*
* @param $text String: diff's HTML output
* @return String: modified HTML
*/
public static function applyDiffStyle( $text ) {
$styles = array(
'diff' => 'background-color: white; color:black;',
'diff-otitle' => 'background-color: white; color:black;',
'diff-ntitle' => 'background-color: white; color:black;',
'diff-addedline' => 'background: #cfc; color:black; font-size: smaller;',
'diff-deletedline' => 'background: #ffa; color:black; font-size: smaller;',
'diff-context' => 'background: #eee; color:black; font-size: smaller;',
'diffchange' => 'color: red; font-weight: bold; text-decoration: none;',
);
foreach( $styles as $class => $style ) {
$text = preg_replace( "/(<[^>]+)class=(['\"])$class\\2([^>]*>)/",
"\\1style=\"$style\"\\3", $text );
}
return $text;
}
}
|