function rcOutputFeed($rows, $feedFormat, $limit, $hideminor, $lastmod) { global $messageMemc, $wgFeedCacheTimeout; global $wgFeedClasses, $wgTitle, $wgSitename, $wgContLanguageCode; if (!isset($wgFeedClasses[$feedFormat])) { wfHttpError(500, "Internal Server Error", "Unsupported feed type."); return false; } $timekey = wfMemcKey('rcfeed', $feedFormat, 'timestamp'); $key = wfMemcKey('rcfeed', $feedFormat, 'limit', $limit, 'minor', $hideminor); $feedTitle = $wgSitename . ' - ' . wfMsgForContent('recentchanges') . ' [' . $wgContLanguageCode . ']'; $feed = new $wgFeedClasses[$feedFormat]($feedTitle, htmlspecialchars(wfMsgForContent('recentchanges-feed-description')), $wgTitle->getFullUrl()); //purge cache if requested global $wgRequest, $wgUser; $purge = $wgRequest->getVal('action') == 'purge'; if ($purge && $wgUser->isAllowed('purge')) { $messageMemc->delete($timekey); $messageMemc->delete($key); } /** * Bumping around loading up diffs can be pretty slow, so where * possible we want to cache the feed output so the next visitor * gets it quick too. */ $cachedFeed = false; if ($wgFeedCacheTimeout > 0 && ($feedLastmod = $messageMemc->get($timekey))) { /** * If the cached feed was rendered very recently, we may * go ahead and use it even if there have been edits made * since it was rendered. This keeps a swarm of requests * from being too bad on a super-frequently edited wiki. */ if (time() - wfTimestamp(TS_UNIX, $feedLastmod) < $wgFeedCacheTimeout || wfTimestamp(TS_UNIX, $feedLastmod) > wfTimestamp(TS_UNIX, $lastmod)) { wfDebug("RC: loading feed from cache ({$key}; {$feedLastmod}; {$lastmod})...\n"); $cachedFeed = $messageMemc->get($key); } else { wfDebug("RC: cached feed timestamp check failed ({$feedLastmod}; {$lastmod})\n"); } } if (is_string($cachedFeed)) { wfDebug("RC: Outputting cached feed\n"); $feed->httpHeaders(); echo $cachedFeed; } else { wfDebug("RC: rendering new feed and caching it\n"); ob_start(); rcDoOutputFeed($rows, $feed); $cachedFeed = ob_get_contents(); ob_end_flush(); $expire = 3600 * 24; # One day $messageMemc->set($key, $cachedFeed); $messageMemc->set($timekey, wfTimestamp(TS_MW), $expire); } return true; }
/** * Entrypoint * @param string $par parent page we will look at */ function wfSpecialRecentchangeslinked($par = NULL) { global $wgUser, $wgOut, $wgLang, $wgContLang, $wgRequest, $wgTitle; $fname = 'wfSpecialRecentchangeslinked'; $days = $wgRequest->getInt('days'); $target = isset($par) ? $par : $wgRequest->getText('target'); $hideminor = $wgRequest->getBool('hideminor') ? 1 : 0; $wgOut->setPagetitle(wfMsg('recentchangeslinked')); $sk = $wgUser->getSkin(); if (is_null($target)) { $wgOut->errorpage('notargettitle', 'notargettext'); return; } $nt = Title::newFromURL($target); if (!$nt) { $wgOut->errorpage('notargettitle', 'notargettext'); return; } $id = $nt->getArticleId(); $wgOut->setPageTitle(wfMsg('recentchangeslinked-title', $nt->getPrefixedText())); $wgOut->setSyndicated(); $wgOut->setFeedAppendQuery("target=" . urlencode($target)); if (!$days) { $days = (int) $wgUser->getOption('rcdays', 7); } list($limit, ) = wfCheckLimits(100, 'rclimit'); $dbr = wfGetDB(DB_SLAVE, 'recentchangeslinked'); $cutoff = $dbr->timestamp(time() - $days * 86400); $hideminor = $hideminor ? 1 : 0; if ($hideminor) { $mlink = $sk->makeKnownLink($wgContLang->specialPage('Recentchangeslinked'), wfMsg('show'), 'target=' . htmlspecialchars($nt->getPrefixedURL()) . "&days={$days}&limit={$limit}&hideminor=0"); } else { $mlink = $sk->makeKnownLink($wgContLang->specialPage("Recentchangeslinked"), wfMsg("hide"), "target=" . htmlspecialchars($nt->getPrefixedURL()) . "&days={$days}&limit={$limit}&hideminor=1"); } if ($hideminor) { $cmq = 'AND rc_minor=0'; } else { $cmq = ''; } list($recentchanges, $categorylinks, $pagelinks, $watchlist) = $dbr->tableNamesN('recentchanges', 'categorylinks', 'pagelinks', "watchlist"); $uid = $wgUser->getID(); $GROUPBY = "\n\tGROUP BY rc_cur_id,rc_namespace,rc_title,\n\t\trc_user,rc_comment,rc_user_text,rc_timestamp,rc_minor,rc_deleted,\n\t\trc_new, rc_id, rc_this_oldid, rc_last_oldid, rc_bot, rc_patrolled, rc_type, rc_old_len, rc_new_len\n" . ($uid ? ",wl_user" : "") . "\n\t\tORDER BY rc_timestamp DESC\n\tLIMIT {$limit}"; // If target is a Category, use categorylinks and invert from and to if ($nt->getNamespace() == NS_CATEGORY) { $catkey = $dbr->addQuotes($nt->getDBkey()); $sql = "SELECT /* wfSpecialRecentchangeslinked */\n\t\t\t\trc_id,\n\t\t\t\trc_cur_id,\n\t\t\t\trc_namespace,\n\t\t\t\trc_title,\n\t\t\t\trc_this_oldid,\n\t\t\t\trc_last_oldid,\n\t\t\t\trc_user,\n\t\t\t\trc_comment,\n\t\t\t\trc_user_text,\n\t\t\t\trc_timestamp,\n\t\t\t\trc_minor,\n\t\t\t\trc_bot,\n\t\t\t\trc_new,\n\t\t\t\trc_patrolled,\n\t\t\t\trc_type,\n\t\t\t\trc_old_len,\n\t\t\t\trc_new_len,\n\t\t\t\trc_deleted\n" . ($uid ? ",wl_user" : "") . "\n\t FROM {$categorylinks}, {$recentchanges}\n" . ($uid ? "LEFT OUTER JOIN {$watchlist} ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace " : "") . "\n\t WHERE rc_timestamp > '{$cutoff}'\n\t {$cmq}\n\t AND cl_from=rc_cur_id\n\t AND cl_to={$catkey}\n{$GROUPBY}\n "; } else { $sql = "SELECT /* wfSpecialRecentchangeslinked */\n\t\t\trc_id,\n\t\t\trc_cur_id,\n\t\t\trc_namespace,\n\t\t\trc_title,\n\t\t\trc_user,\n\t\t\trc_comment,\n\t\t\trc_user_text,\n\t\t\trc_this_oldid,\n\t\t\trc_last_oldid,\n\t\t\trc_timestamp,\n\t\t\trc_minor,\n\t\t\trc_bot,\n\t\t\trc_new,\n\t\t\trc_patrolled,\n\t\t\trc_type,\n\t\t\trc_old_len,\n\t\t\trc_new_len,\n\t\t\trc_deleted\n" . ($uid ? ",wl_user" : "") . "\n FROM {$pagelinks}, {$recentchanges}\n" . ($uid ? " LEFT OUTER JOIN {$watchlist} ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace " : "") . "\n WHERE rc_timestamp > '{$cutoff}'\n\t{$cmq}\n AND pl_namespace=rc_namespace\n AND pl_title=rc_title\n AND pl_from={$id}\n{$GROUPBY}\n"; } $res = $dbr->query($sql, $fname); $wgOut->addHTML("< " . $sk->makeLinkObj($nt, "", "redirect=no") . "<br />\n"); $note = wfMsgExt("rcnote", array('parseinline'), $limit, $days, $wgLang->timeAndDate(wfTimestampNow(), true)); $wgOut->addHTML("<hr />\n{$note}\n<br />"); $note = rcDayLimitlinks($days, $limit, "Recentchangeslinked", "target=" . $nt->getPrefixedURL() . "&hideminor={$hideminor}", false, $mlink); $wgOut->addHTML($note . "\n"); $list = ChangesList::newFromUser($wgUser); $s = $list->beginRecentChangesList(); $count = $dbr->numRows($res); $rchanges = array(); if ($count) { $counter = 1; while ($limit) { if (0 == $count) { break; } $obj = $dbr->fetchObject($res); --$count; $rc = RecentChange::newFromRow($obj); $rc->counter = $counter++; $s .= $list->recentChangesLine($rc, !empty($obj->wl_user)); --$limit; $rchanges[] = $obj; } } else { $wgOut->addWikiMsg('recentchangeslinked-noresult'); } $s .= $list->endRecentChangesList(); $dbr->freeResult($res); $wgOut->addHTML($s); global $wgSitename, $wgFeedClasses, $wgContLanguageCode; $feedFormat = $wgRequest->getVal('feed'); if ($feedFormat && isset($wgFeedClasses[$feedFormat])) { $feedTitle = $wgSitename . ' - ' . wfMsgForContent('recentchangeslinked-title', $nt->getPrefixedText()) . ' [' . $wgContLanguageCode . ']'; $feed = new $wgFeedClasses[$feedFormat]($feedTitle, htmlspecialchars(wfMsgForContent('recentchangeslinked')), $wgTitle->getFullUrl()); require_once "SpecialRecentchanges.php"; $wgOut->disable(); rcDoOutputFeed($rchanges, $feed); } }