From c3940d01d619257ac5829e9c39a89a2443d5a220 Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Wed, 8 May 2019 17:21:36 -0700 Subject: [PATCH] Fix stale client caching of history pages with $wgShowUpdateMarker enabled Change-Id: I5b9d986e4f34166f2a1602129d2e01573bfe7ac5 --- includes/Title.php | 2 +- includes/actions/HistoryAction.php | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/includes/Title.php b/includes/Title.php index a956ca2176..b9b1bb7947 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -4262,7 +4262,7 @@ class Title implements LinkTarget, IDBAccessObject { * Get the timestamp when this page was updated since the user last saw it. * * @param User|null $user - * @return string|null + * @return string|bool|null String timestamp, false if not watched, null if nothing is unseen */ public function getNotificationTimestamp( $user = null ) { global $wgUser; diff --git a/includes/actions/HistoryAction.php b/includes/actions/HistoryAction.php index 4df2f563c7..958ec06f47 100644 --- a/includes/actions/HistoryAction.php +++ b/includes/actions/HistoryAction.php @@ -148,10 +148,17 @@ class HistoryAction extends FormlessAction { $out = $this->getOutput(); $request = $this->getRequest(); - /** - * Allow client caching. - */ - if ( $out->checkLastModified( $this->page->getTouched() ) ) { + // Allow client-side HTTP caching of the history page. + // But, always ignore this cache if the (logged-in) user has this page on their watchlist + // and has one or more unseen revisions. Otherwise, we might be showing stale update markers. + // The Last-Modified for the history page does not change when user's markers are cleared, + // so going from "some unseen" to "all seen" would not clear the cache. + // But, when all of the revisions are marked as seen, then only way for new unseen revision + // markers to appear, is for the page to be edited, which updates page_touched/Last-Modified. + if ( + !$this->hasUnseenRevisionMarkers() && + $out->checkLastModified( $this->page->getTouched() ) + ) { return null; // Client cache fresh and headers sent, nothing more to do. } @@ -305,6 +312,16 @@ class HistoryAction extends FormlessAction { return null; } + /** + * @return bool Page is watched by and has unseen revision for the user + */ + private function hasUnseenRevisionMarkers() { + return ( + $this->getContext()->getConfig()->get( 'ShowUpdatedMarker' ) && + $this->getTitle()->getNotificationTimestamp( $this->getUser() ) + ); + } + /** * Fetch an array of revisions, specified by a given limit, offset and * direction. This is now only used by the feeds. It was previously -- 2.20.1