summaryrefslogtreecommitdiff
path: root/includes/actions
diff options
context:
space:
mode:
Diffstat (limited to 'includes/actions')
-rw-r--r--includes/actions/Action.php10
-rw-r--r--includes/actions/DeleteAction.php2
-rw-r--r--includes/actions/EditAction.php2
-rw-r--r--includes/actions/HistoryAction.php33
-rw-r--r--includes/actions/InfoAction.php95
-rw-r--r--includes/actions/RawAction.php52
-rw-r--r--includes/actions/RevertAction.php2
-rw-r--r--includes/actions/RollbackAction.php3
-rw-r--r--includes/actions/UnprotectAction.php1
-rw-r--r--includes/actions/WatchAction.php2
10 files changed, 146 insertions, 56 deletions
diff --git a/includes/actions/Action.php b/includes/actions/Action.php
index bb6a4d5d..43f03c3a 100644
--- a/includes/actions/Action.php
+++ b/includes/actions/Action.php
@@ -407,4 +407,14 @@ abstract class Action {
* @throws ErrorPageError
*/
abstract public function show();
+
+ /**
+ * Call wfTransactionalTimeLimit() if this request was POSTed
+ * @since 1.26
+ */
+ protected function useTransactionalTimeLimit() {
+ if ( $this->getRequest()->wasPosted() ) {
+ wfTransactionalTimeLimit();
+ }
+ }
}
diff --git a/includes/actions/DeleteAction.php b/includes/actions/DeleteAction.php
index be21a6f1..841a94df 100644
--- a/includes/actions/DeleteAction.php
+++ b/includes/actions/DeleteAction.php
@@ -41,6 +41,8 @@ class DeleteAction extends FormlessAction {
}
public function show() {
+ $this->useTransactionalTimeLimit();
+
$out = $this->getOutput();
if ( $this->getContext()->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
$out->addModuleStyles( array(
diff --git a/includes/actions/EditAction.php b/includes/actions/EditAction.php
index 6c8440ac..eb53f19a 100644
--- a/includes/actions/EditAction.php
+++ b/includes/actions/EditAction.php
@@ -41,6 +41,8 @@ class EditAction extends FormlessAction {
}
public function show() {
+ $this->useTransactionalTimeLimit();
+
if ( $this->getContext()->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
$out = $this->getOutput();
$out->addModuleStyles( array(
diff --git a/includes/actions/HistoryAction.php b/includes/actions/HistoryAction.php
index dcd77415..a81adf99 100644
--- a/includes/actions/HistoryAction.php
+++ b/includes/actions/HistoryAction.php
@@ -368,6 +368,9 @@ class HistoryPager extends ReverseChronologicalPager {
*/
protected $parentLens;
+ /** @var bool Whether to show the tag editing UI */
+ protected $showTagEditUI;
+
/**
* @param HistoryAction $historyPage
* @param string $year
@@ -381,6 +384,7 @@ class HistoryPager extends ReverseChronologicalPager {
$this->tagFilter = $tagFilter;
$this->getDateCond( $year, $month );
$this->conds = $conds;
+ $this->showTagEditUI = ChangeTags::showTagEditingUI( $this->getUser() );
}
// For hook compatibility...
@@ -432,8 +436,13 @@ class HistoryPager extends ReverseChronologicalPager {
$latest = ( $this->counter == 1 && $this->mIsFirst );
$firstInList = $this->counter == 1;
$this->counter++;
- $s = $this->historyLine( $this->lastRow, $row,
- $this->getTitle()->getNotificationTimestamp( $this->getUser() ), $latest, $firstInList );
+
+ $notifTimestamp = $this->getConfig()->get( 'ShowUpdatedMarker' )
+ ? $this->getTitle()->getNotificationTimestamp( $this->getUser() )
+ : false;
+
+ $s = $this->historyLine(
+ $this->lastRow, $row, $notifTimestamp, $latest, $firstInList );
} else {
$s = '';
}
@@ -443,6 +452,10 @@ class HistoryPager extends ReverseChronologicalPager {
}
function doBatchLookups() {
+ if ( !Hooks::run( 'PageHistoryPager::doBatchLookups', array( $this, $this->mResult ) ) ) {
+ return;
+ }
+
# Do a link batch query
$this->mResult->seek( 0 );
$batch = new LinkBatch();
@@ -495,7 +508,7 @@ class HistoryPager extends ReverseChronologicalPager {
if ( $user->isAllowed( 'deleterevision' ) ) {
$actionButtons .= $this->getRevisionButton( 'revisiondelete', 'showhideselectedversions' );
}
- if ( ChangeTags::showTagEditingUI( $user ) ) {
+ if ( $this->showTagEditUI ) {
$actionButtons .= $this->getRevisionButton( 'editchangetags', 'history-edit-tags' );
}
if ( $actionButtons ) {
@@ -542,8 +555,13 @@ class HistoryPager extends ReverseChronologicalPager {
$next = $this->mPastTheEndRow;
}
$this->counter++;
- $s = $this->historyLine( $this->lastRow, $next,
- $this->getTitle()->getNotificationTimestamp( $this->getUser() ), $latest, $firstInList );
+
+ $notifTimestamp = $this->getConfig()->get( 'ShowUpdatedMarker' )
+ ? $this->getTitle()->getNotificationTimestamp( $this->getUser() )
+ : false;
+
+ $s = $this->historyLine(
+ $this->lastRow, $next, $notifTimestamp, $latest, $firstInList );
} else {
$s = '';
}
@@ -617,14 +635,13 @@ class HistoryPager extends ReverseChronologicalPager {
$del = '';
$user = $this->getUser();
$canRevDelete = $user->isAllowed( 'deleterevision' );
- $showTagEditUI = ChangeTags::showTagEditingUI( $user );
// Show checkboxes for each revision, to allow for revision deletion and
// change tags
- if ( $canRevDelete || $showTagEditUI ) {
+ if ( $canRevDelete || $this->showTagEditUI ) {
$this->preventClickjacking();
// If revision was hidden from sysops and we don't need the checkbox
// for anything else, disable it
- if ( !$showTagEditUI && !$rev->userCan( Revision::DELETED_RESTRICTED, $user ) ) {
+ if ( !$this->showTagEditUI && !$rev->userCan( Revision::DELETED_RESTRICTED, $user ) ) {
$del = Xml::check( 'deleterevisions', false, array( 'disabled' => 'disabled' ) );
// Otherwise, enable the checkbox...
} else {
diff --git a/includes/actions/InfoAction.php b/includes/actions/InfoAction.php
index b5a73910..f3670a86 100644
--- a/includes/actions/InfoAction.php
+++ b/includes/actions/InfoAction.php
@@ -62,14 +62,18 @@ class InfoAction extends FormlessAction {
*
* @since 1.22
* @param Title $title Title to clear cache for
+ * @param int|null $revid Revision id to clear
*/
- public static function invalidateCache( Title $title ) {
- global $wgMemc;
+ public static function invalidateCache( Title $title, $revid = null ) {
+ $cache = ObjectCache::getMainWANInstance();
- $revision = Revision::newFromTitle( $title, 0, Revision::READ_LATEST );
- if ( $revision !== null ) {
- $key = wfMemcKey( 'infoaction', sha1( $title->getPrefixedText() ), $revision->getId() );
- $wgMemc->delete( $key );
+ if ( !$revid ) {
+ $revision = Revision::newFromTitle( $title, 0, Revision::READ_LATEST );
+ $revid = $revision ? $revision->getId() : null;
+ }
+ if ( $revid !== null ) {
+ $key = wfMemcKey( 'infoaction', sha1( $title->getPrefixedText() ), $revid );
+ $cache->delete( $key );
}
}
@@ -193,7 +197,7 @@ class InfoAction extends FormlessAction {
* @return array
*/
protected function pageInfo() {
- global $wgContLang, $wgMemc;
+ global $wgContLang;
$user = $this->getUser();
$lang = $this->getLanguage();
@@ -201,16 +205,17 @@ class InfoAction extends FormlessAction {
$id = $title->getArticleID();
$config = $this->context->getConfig();
+ $cache = ObjectCache::getMainWANInstance();
$memcKey = wfMemcKey( 'infoaction',
sha1( $title->getPrefixedText() ), $this->page->getLatest() );
- $pageCounts = $wgMemc->get( $memcKey );
+ $pageCounts = $cache->get( $memcKey );
$version = isset( $pageCounts['cacheversion'] ) ? $pageCounts['cacheversion'] : false;
if ( $pageCounts === false || $version !== self::CACHE_VERSION ) {
// Get page information that would be too "expensive" to retrieve by normal means
$pageCounts = $this->pageCounts( $title );
$pageCounts['cacheversion'] = self::CACHE_VERSION;
- $wgMemc->set( $memcKey, $pageCounts );
+ $cache->set( $memcKey, $pageCounts );
}
// Get page properties
@@ -233,7 +238,7 @@ class InfoAction extends FormlessAction {
// Display title
$displayTitle = $title->getPrefixedText();
- if ( !empty( $pageProperties['displaytitle'] ) ) {
+ if ( isset( $pageProperties['displaytitle'] ) ) {
$displayTitle = $pageProperties['displaytitle'];
}
@@ -258,7 +263,7 @@ class InfoAction extends FormlessAction {
// Default sort key
$sortKey = $title->getCategorySortkey();
- if ( !empty( $pageProperties['defaultsort'] ) ) {
+ if ( isset( $pageProperties['defaultsort'] ) ) {
$sortKey = $pageProperties['defaultsort'];
}
@@ -324,8 +329,27 @@ class InfoAction extends FormlessAction {
) {
// Number of page watchers
$pageInfo['header-basic'][] = array(
- $this->msg( 'pageinfo-watchers' ), $lang->formatNum( $pageCounts['watchers'] )
+ $this->msg( 'pageinfo-watchers' ),
+ $lang->formatNum( $pageCounts['watchers'] )
);
+ if (
+ $config->get( 'ShowUpdatedMarker' ) &&
+ isset( $pageCounts['visitingWatchers'] )
+ ) {
+ $minToDisclose = $config->get( 'UnwatchedPageSecret' );
+ if ( $pageCounts['visitingWatchers'] > $minToDisclose ||
+ $user->isAllowed( 'unwatchedpages' ) ) {
+ $pageInfo['header-basic'][] = array(
+ $this->msg( 'pageinfo-visiting-watchers' ),
+ $lang->formatNum( $pageCounts['visitingWatchers'] )
+ );
+ } else {
+ $pageInfo['header-basic'][] = array(
+ $this->msg( 'pageinfo-visiting-watchers' ),
+ $this->msg( 'pageinfo-few-visiting-watchers' )
+ );
+ }
+ }
} elseif ( $unwatchedPageThreshold !== false ) {
$pageInfo['header-basic'][] = array(
$this->msg( 'pageinfo-watchers' ),
@@ -373,18 +397,30 @@ class InfoAction extends FormlessAction {
if ( $title->inNamespace( NS_CATEGORY ) ) {
$category = Category::newFromTitle( $title );
+
+ // $allCount is the total number of cat members,
+ // not the count of how many members are normal pages.
+ $allCount = (int)$category->getPageCount();
+ $subcatCount = (int)$category->getSubcatCount();
+ $fileCount = (int)$category->getFileCount();
+ $pagesCount = $allCount - $subcatCount - $fileCount;
+
$pageInfo['category-info'] = array(
array(
+ $this->msg( 'pageinfo-category-total' ),
+ $lang->formatNum( $allCount )
+ ),
+ array(
$this->msg( 'pageinfo-category-pages' ),
- $lang->formatNum( $category->getPageCount() )
+ $lang->formatNum( $pagesCount )
),
array(
$this->msg( 'pageinfo-category-subcats' ),
- $lang->formatNum( $category->getSubcatCount() )
+ $lang->formatNum( $subcatCount )
),
array(
$this->msg( 'pageinfo-category-files' ),
- $lang->formatNum( $category->getFileCount() )
+ $lang->formatNum( $fileCount )
)
);
}
@@ -434,6 +470,10 @@ class InfoAction extends FormlessAction {
$message = $message->escaped();
}
}
+ $expiry = $title->getRestrictionExpiry( $restrictionType );
+ $formattedexpiry = $this->msg( 'parentheses',
+ $this->getLanguage()->formatExpiry( $expiry ) )->escaped();
+ $message .= $this->msg( 'word-separator' )->escaped() . $formattedexpiry;
// Messages: restriction-edit, restriction-move, restriction-create,
// restriction-upload
@@ -639,11 +679,11 @@ class InfoAction extends FormlessAction {
$id = $title->getArticleID();
$config = $this->context->getConfig();
- $dbr = wfGetDB( DB_SLAVE );
+ $dbrWatchlist = wfGetDB( DB_SLAVE, 'watchlist' );
$result = array();
// Number of page watchers
- $watchers = (int)$dbr->selectField(
+ $watchers = (int)$dbrWatchlist->selectField(
'watchlist',
'COUNT(*)',
array(
@@ -654,6 +694,27 @@ class InfoAction extends FormlessAction {
);
$result['watchers'] = $watchers;
+ if ( $config->get( 'ShowUpdatedMarker' ) ) {
+ // Threshold: last visited about 26 weeks before latest edit
+ $updated = wfTimestamp( TS_UNIX, $this->page->getTimestamp() );
+ $age = $config->get( 'WatchersMaxAge' );
+ $threshold = $dbrWatchlist->timestamp( $updated - $age );
+ // Number of page watchers who also visited a "recent" edit
+ $visitingWatchers = (int)$dbrWatchlist->selectField(
+ 'watchlist',
+ 'COUNT(*)',
+ array(
+ 'wl_namespace' => $title->getNamespace(),
+ 'wl_title' => $title->getDBkey(),
+ 'wl_notificationtimestamp >= ' . $dbrWatchlist->addQuotes( $threshold ) .
+ ' OR wl_notificationtimestamp IS NULL'
+ ),
+ __METHOD__
+ );
+ $result['visitingWatchers'] = $visitingWatchers;
+ }
+
+ $dbr = wfGetDB( DB_SLAVE );
// Total number of edits
$edits = (int)$dbr->selectField(
'revision',
diff --git a/includes/actions/RawAction.php b/includes/actions/RawAction.php
index 727bed20..b71b0e9e 100644
--- a/includes/actions/RawAction.php
+++ b/includes/actions/RawAction.php
@@ -34,10 +34,10 @@
*/
class RawAction extends FormlessAction {
/**
- * @var bool Does the request include a gen=css|javascript parameter
- * @deprecated This used to be a string for "css" or "javascript" but
- * it is no longer used. Setting this parameter results in empty content
- * being served
+ * Whether the request includes a 'gen' parameter
+ * @var bool
+ * @deprecated since 1.17 This used to be a string for "css" or "javascript" but
+ * it is no longer used. Setting this parameter results in an empty response.
*/
private $gen = false;
@@ -56,6 +56,7 @@ class RawAction extends FormlessAction {
function onView() {
$this->getOutput()->disable();
$request = $this->getRequest();
+ $response = $request->response();
$config = $this->context->getConfig();
if ( !$request->checkUrlExtension() ) {
@@ -66,42 +67,35 @@ class RawAction extends FormlessAction {
return; // Client cache fresh and headers sent, nothing more to do.
}
- # special case for 'generated' raw things: user css/js
- # This is deprecated and will only return empty content
$gen = $request->getVal( 'gen' );
- $smaxage = $request->getIntOrNull( 'smaxage' );
-
if ( $gen == 'css' || $gen == 'js' ) {
$this->gen = true;
- if ( $smaxage === null ) {
- $smaxage = $config->get( 'SquidMaxage' );
- }
}
$contentType = $this->getContentType();
- # Force caching for CSS and JS raw content, default: 5 minutes.
- # Note: If using a canonical url for userpage css/js, we send an HTCP purge.
+ $maxage = $request->getInt( 'maxage', $config->get( 'SquidMaxage' ) );
+ $smaxage = $request->getIntOrNull( 'smaxage' );
if ( $smaxage === null ) {
- if ( $contentType == 'text/css' || $contentType == 'text/javascript' ) {
+ if ( $this->gen ) {
+ $smaxage = $config->get( 'SquidMaxage' );
+ } elseif ( $contentType == 'text/css' || $contentType == 'text/javascript' ) {
+ // CSS/JS raw content has its own squid max age configuration.
+ // Note: Title::getSquidURLs() includes action=raw for css/js pages,
+ // so if using the canonical url, this will get HTCP purges.
$smaxage = intval( $config->get( 'ForcedRawSMaxage' ) );
} else {
+ // No squid cache for anything else
$smaxage = 0;
}
}
- $maxage = $request->getInt( 'maxage', $config->get( 'SquidMaxage' ) );
-
- $response = $request->response();
-
$response->header( 'Content-type: ' . $contentType . '; charset=UTF-8' );
- # Output may contain user-specific data;
- # vary generated content for open sessions on private wikis
+ // Output may contain user-specific data;
+ // vary generated content for open sessions on private wikis
$privateCache = !User::isEveryoneAllowed( 'read' ) && ( $smaxage == 0 || session_id() != '' );
- // Bug 53032 - make this private if user is logged in,
- // so we don't accidentally cache cookies
- $privateCache = $privateCache ?: $this->getUser()->isLoggedIn();
- # allow the client to cache this for 24 hours
+ // Don't accidentally cache cookies if user is logged in (T55032)
+ $privateCache = $privateCache || $this->getUser()->isLoggedIn();
$mode = $privateCache ? 'private' : 'public';
$response->header(
'Cache-Control: ' . $mode . ', s-maxage=' . $smaxage . ', max-age=' . $maxage
@@ -109,12 +103,12 @@ class RawAction extends FormlessAction {
$text = $this->getRawText();
+ // Don't return a 404 response for CSS or JavaScript;
+ // 404s aren't generally cached and it would create
+ // extra hits when user CSS/JS are on and the user doesn't
+ // have the pages.
if ( $text === false && $contentType == 'text/x-wiki' ) {
- # Don't return a 404 response for CSS or JavaScript;
- # 404s aren't generally cached and it would create
- # extra hits when user CSS/JS are on and the user doesn't
- # have the pages.
- $response->header( 'HTTP/1.x 404 Not Found' );
+ $response->statusHeader( 404 );
}
if ( !Hooks::run( 'RawPageViewBeforeOutput', array( &$this, &$text ) ) ) {
diff --git a/includes/actions/RevertAction.php b/includes/actions/RevertAction.php
index d0258784..c7f33463 100644
--- a/includes/actions/RevertAction.php
+++ b/includes/actions/RevertAction.php
@@ -107,6 +107,8 @@ class RevertAction extends FormAction {
}
public function onSubmit( $data ) {
+ $this->useTransactionalTimeLimit();
+
$source = $this->page->getFile()->getArchiveVirtualUrl(
$this->getRequest()->getText( 'oldimage' )
);
diff --git a/includes/actions/RollbackAction.php b/includes/actions/RollbackAction.php
index 76d70d70..93669cf4 100644
--- a/includes/actions/RollbackAction.php
+++ b/includes/actions/RollbackAction.php
@@ -36,6 +36,9 @@ class RollbackAction extends FormlessAction {
}
public function onView() {
+ // TODO: use $this->useTransactionalTimeLimit(); when POST only
+ wfTransactionalTimeLimit();
+
$details = null;
$request = $this->getRequest();
diff --git a/includes/actions/UnprotectAction.php b/includes/actions/UnprotectAction.php
index bc28c8ed..559cfaf7 100644
--- a/includes/actions/UnprotectAction.php
+++ b/includes/actions/UnprotectAction.php
@@ -37,7 +37,6 @@ class UnprotectAction extends ProtectAction {
}
public function show() {
-
$this->page->unprotect();
}
}
diff --git a/includes/actions/WatchAction.php b/includes/actions/WatchAction.php
index 96473409..8b6e329d 100644
--- a/includes/actions/WatchAction.php
+++ b/includes/actions/WatchAction.php
@@ -64,7 +64,7 @@ class WatchAction extends FormAction {
$this->checkCanExecute( $user );
// Must have valid token for this action/title
- $salt = array( $this->getName(), $this->getTitle()->getDBkey() );
+ $salt = array( $this->getName(), $this->getTitle()->getPrefixedDBkey() );
if ( $user->matchEditToken( $this->getRequest()->getVal( 'token' ), $salt ) ) {
$this->onSubmit( array() );