Cenarium has uploaded a new change for review. https://gerrit.wikimedia.org/r/251795
Change subject: Allow patrol of uploads ...................................................................... Allow patrol of uploads This allows to patrol file uploads, both new files and new file versions, from the description page, provided $wgUseFilePatrol is set to true. Special:NewFiles can be filtered to hide patrolled files. Bug: T11501 Change-Id: If71af58719a4461f12d125455b7bef07164525ca --- M includes/DefaultSettings.php M includes/User.php M includes/changes/ChangesList.php M includes/changes/RecentChange.php M includes/filerepo/file/LocalFile.php M includes/page/Article.php M includes/specials/SpecialNewimages.php M languages/i18n/en.json M languages/i18n/qqq.json 9 files changed, 140 insertions(+), 17 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core refs/changes/95/251795/1 diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index bf6e245..b9d0921 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -6194,7 +6194,8 @@ $wgRCWatchCategoryMembership = false; /** - * Use RC Patrolling to check for vandalism + * Use RC Patrolling to check for vandalism (from recent changes and watchlists) + * New pages and new files are included. */ $wgUseRCPatrol = true; @@ -6204,6 +6205,11 @@ $wgUseNPPatrol = true; /** + * Use file patrolling to check new files on Special:Newfiles + */ +$wgUseFilePatrol = true; + +/** * Log autopatrol actions to the log table */ $wgLogAutopatrol = true; diff --git a/includes/User.php b/includes/User.php index b09e4e4..14de569 100644 --- a/includes/User.php +++ b/includes/User.php @@ -3311,6 +3311,18 @@ } /** + * Check whether to enable new files patrol features for this user + * @return bool True or false + */ + public function useFilePatrol() { + global $wgUseRCPatrol, $wgUseFilePatrol; + return ( + ( $wgUseRCPatrol || $wgUseFilePatrol ) + && ( $this->isAllowedAny( 'patrol', 'patrolmarks' ) ) + ); + } + + /** * Get the WebRequest object to use with this object * * @return WebRequest diff --git a/includes/changes/ChangesList.php b/includes/changes/ChangesList.php index 2494ef1..6081a17 100644 --- a/includes/changes/ChangesList.php +++ b/includes/changes/ChangesList.php @@ -638,9 +638,11 @@ if ( $rc instanceof RecentChange ) { $isPatrolled = $rc->mAttribs['rc_patrolled']; $rcType = $rc->mAttribs['rc_type']; + $rcLogType = $rc->mAttribs['rc_log_type']; } else { $isPatrolled = $rc->rc_patrolled; $rcType = $rc->rc_type; + $rcLogType = $rc->rc_log_type; } if ( !$isPatrolled ) { @@ -650,6 +652,9 @@ if ( $user->useNPPatrol() && $rcType == RC_NEW ) { return true; } + if ( $user->useFilePatrol() && $rcLogType == 'upload' ) { + return true; + } } return false; diff --git a/includes/changes/RecentChange.php b/includes/changes/RecentChange.php index b0b88d3..df3b5bc 100644 --- a/includes/changes/RecentChange.php +++ b/includes/changes/RecentChange.php @@ -456,11 +456,13 @@ * @return array Array of permissions errors, see Title::getUserPermissionsErrors() */ public function doMarkPatrolled( User $user, $auto = false ) { - global $wgUseRCPatrol, $wgUseNPPatrol; + global $wgUseRCPatrol, $wgUseNPPatrol, $wgUseFilePatrol; $errors = array(); - // If recentchanges patrol is disabled, only new pages - // can be patrolled - if ( !$wgUseRCPatrol && ( !$wgUseNPPatrol || $this->getAttribute( 'rc_type' ) != RC_NEW ) ) { + // If recentchanges patrol is disabled, only new pages or new file versions + // can be patrolled, provided the appropriate config variable is set + if ( !$wgUseRCPatrol && ( !$wgUseNPPatrol || $this->getAttribute( 'rc_type' ) != RC_NEW ) && + ( !$wgUseFilePatrol || !( $this->getAttribute( 'rc_type' ) == RC_LOG && + $this->getAttribute( 'rc_log_type' ) == 'upload' ) ) ) { $errors[] = array( 'rcpatroldisabled' ); } // Automatic patrol needs "autopatrol", ordinary patrol needs "patrol" diff --git a/includes/filerepo/file/LocalFile.php b/includes/filerepo/file/LocalFile.php index cd64f0d..1f78a48 100644 --- a/includes/filerepo/file/LocalFile.php +++ b/includes/filerepo/file/LocalFile.php @@ -1340,6 +1340,7 @@ } $descTitle = $this->getTitle(); + $descId = $descTitle->getArticleID(); $wikiPage = new WikiFilePage( $descTitle ); $wikiPage->setFile( $this ); @@ -1365,8 +1366,6 @@ $logId = $logEntry->insert(); if ( $descTitle->exists() ) { - // Page exists, do RC entry now (otherwise we wait for later) - $logEntry->publish( $logId ); // Use own context to get the action text in content language $formatter = LogFormatter::newFromEntry( $logEntry ); $formatter->setContext( RequestContext::newExtraneousContext( $descTitle ) ); @@ -1374,7 +1373,7 @@ $nullRevision = Revision::newNullRevision( $dbw, - $descTitle->getArticleID(), + $descId, $editSummary, false, $user @@ -1386,7 +1385,11 @@ array( $wikiPage, $nullRevision, $nullRevision->getParentId(), $user ) ); $wikiPage->updateRevisionOn( $dbw, $nullRevision ); + // Associate null revision id + $logEntry->setAssociatedRevId( $nullRevision->getId() ); } + // Page exists, do RC entry now (otherwise we wait for later) + $logEntry->publish( $logId ); $newPageContent = null; } else { @@ -1403,7 +1406,8 @@ # b) They won't cause rollback of the log publish/update above $that = $this; $dbw->onTransactionIdle( function () use ( - $that, $reupload, $wikiPage, $newPageContent, $comment, $user, $logEntry, $logId + $that, $reupload, $wikiPage, $newPageContent, $comment, $user, $logEntry, $logId, + $descId ) { # Update memcache after the commit $that->invalidateCache(); @@ -1420,6 +1424,10 @@ $user ); + if ( isset( $status->value['revision'] ) ) { + // Associate new page revision id + $logEntry->setAssociatedRevId( $status->value['revision']->getId() ); + } // Now that the page exists, make an RC entry. // This relies on the resetArticleID() call in WikiPage::insertOn(), // which is triggered on $descTitle by doEditContent() above. @@ -1438,6 +1446,8 @@ # Existing file page: invalidate description page cache $wikiPage->getTitle()->invalidateCache(); $wikiPage->getTitle()->purgeSquid(); + # Allow the new file version to be patrolled from the page footer + Article::purgePatrolFooterCache( $descId ); } # Run hook for other updates (typically more cache purging) diff --git a/includes/page/Article.php b/includes/page/Article.php index 5d6435e..6865543 100644 --- a/includes/page/Article.php +++ b/includes/page/Article.php @@ -1071,14 +1071,14 @@ * @return bool */ public function showPatrolFooter() { - global $wgUseNPPatrol, $wgUseRCPatrol, $wgEnableAPI, $wgEnableWriteAPI; + global $wgUseNPPatrol, $wgUseRCPatrol, $wgUseFilePatrol, $wgEnableAPI, $wgEnableWriteAPI; $outputPage = $this->getContext()->getOutput(); $user = $this->getContext()->getUser(); $rc = false; if ( !$this->getTitle()->quickUserCan( 'patrol', $user ) - || !( $wgUseRCPatrol || $wgUseNPPatrol ) + || !( $wgUseRCPatrol || $wgUseNPPatrol || $wgUseFilePatrol ) ) { // Patrolling is disabled or the user isn't allowed to return false; @@ -1127,9 +1127,46 @@ __METHOD__ ); } else { - // Cache the information we gathered above in case we can't patrol - // Don't cache in case we can patrol as this could change - $cache->set( $key, '1' ); + if ( $rc ) { + // Use generic patrol message for new pages + $markPatrolledMsg = wfMessage( 'markaspatrolledtext' ); + // Suggest returning to new pages special page + $returnToSpecialPage = 'NewPages'; + } + } + + // Allow patrolling of latest file upload + if ( !$rc && $wgUseFilePatrol && $this->getTitle()->getNamespace() === NS_FILE ) { + // Retrieve timestamp of most recent upload + $newestUploadTimestamp = $dbr->selectField( + 'image', + 'MAX( img_timestamp )', + array( 'img_name' => $this->getTitle()->getDBkey() ), + __METHOD__ + ); + if ( $newestUploadTimestamp + && RecentChange::isInRCLifespan( $newestUploadTimestamp, 21600 ) + ) { + // 6h tolerance because the RC might not be cleaned out regularly + $rc = RecentChange::newFromConds( + array( + 'rc_type' => RC_LOG, + 'rc_log_type' => 'upload', + 'rc_timestamp' => $newestUploadTimestamp, + 'rc_namespace' => NS_FILE, + 'rc_cur_id' => $this->getTitle()->getArticleID(), + 'rc_patrolled' => 0 + ), + __METHOD__, + array( 'USE INDEX' => 'rc_timestamp' ) + ); + } + if ( $rc ) { + // Use patrol message specific to files + $markPatrolledMsg = wfMessage( 'markaspatrolledtext-file' ); + // Suggest returning to new files special page + $returnToSpecialPage = 'NewFiles'; + } } if ( !$rc ) { @@ -1166,12 +1203,13 @@ $link = Linker::linkKnown( $this->getTitle(), - wfMessage( 'markaspatrolledtext' )->escaped(), + $markPatrolledMsg->escaped(), array(), array( 'action' => 'markpatrolled', 'rcid' => $rcid, 'token' => $token, + 'wpReturnToSpecial' => $returnToSpecialPage ) ); @@ -1185,6 +1223,17 @@ } /** + * Purge the cache used to check if it is worth showing the patrol footer + * For example, it is done during re-uploads when file patrol is used. + * @param int $articleID ID of the article to purge + * @since 1.27 + */ + public static function purgePatrolFooterCache( $articleID ) { + $cache = ObjectCache::getMainWANInstance(); + $cache->touchCheckKey( wfMemcKey( 'unpatrollable-page', $articleID ) ); + } + + /** * Show the error text for a missing article. For articles in the MediaWiki * namespace, show the default message text. To be called from Article::view(). */ diff --git a/includes/specials/SpecialNewimages.php b/includes/specials/SpecialNewimages.php index 00c8e05..8aba05b 100644 --- a/includes/specials/SpecialNewimages.php +++ b/includes/specials/SpecialNewimages.php @@ -81,9 +81,20 @@ */ protected $gallery; + /** + * @var bool + */ + protected $showBots; + + /** + * @var bool + */ + protected $hidePatrolled; + function __construct( IContextSource $context, $par = null ) { $this->like = $context->getRequest()->getText( 'like' ); - $this->showbots = $context->getRequest()->getBool( 'showbots', 0 ); + $this->showBots = $context->getRequest()->getBool( 'showbots', 0 ); + $this->hidePatrolled = $context->getRequest()->getBool( 'hidepatrolled', 0 ); if ( is_numeric( $par ) ) { $this->setLimit( $par ); } @@ -95,7 +106,7 @@ $conds = $jconds = array(); $tables = array( 'image' ); - if ( !$this->showbots ) { + if ( !$this->showBots ) { $groupsWithBotPermission = User::getGroupsWithPermission( 'bot' ); if ( count( $groupsWithBotPermission ) ) { @@ -109,6 +120,21 @@ ) ); } + } + + if ( $this->hidePatrolled ) { + $tables[] = 'recentchanges'; + $conds['rc_type'] = RC_LOG; + $conds['rc_log_type'] = 'upload'; + $conds['rc_patrolled'] = 0; + $jconds['recentchanges'] = array( + 'INNER JOIN', + array( + 'rc_title = img_name', + 'rc_user = img_user', + 'rc_timestamp = img_timestamp' + ) + ); } if ( !$this->getConfig()->get( 'MiserMode' ) && $this->like !== null ) { @@ -185,6 +211,11 @@ 'label-message' => 'newimages-showbots', 'name' => 'showbots', ), + 'hidepatrolled' => array( + 'type' => 'check', + 'label-message' => 'newimages-hidepatrolled', + 'name' => 'hidepatrolled', + ), 'limit' => array( 'type' => 'hidden', 'default' => $this->mLimit, @@ -201,6 +232,10 @@ unset( $fields['like'] ); } + if ( !$this->getUser()->useFilePatrol() ) { + unset( $fields['hidepatrolled'] ); + } + $context = new DerivativeContext( $this->getContext() ); $context->setTitle( $this->getTitle() ); // Remove subpage $form = new HTMLForm( $fields, $context ); diff --git a/languages/i18n/en.json b/languages/i18n/en.json index c4e7d92..74aa889 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -2672,6 +2672,7 @@ "markaspatrolleddiff": "Mark as patrolled", "markaspatrolledlink": "[$1]", "markaspatrolledtext": "Mark this page as patrolled", + "markaspatrolledtext-file": "Mark this file version as patrolled", "markedaspatrolled": "Marked as patrolled", "markedaspatrolledtext": "The selected revision of [[:$1]] has been marked as patrolled.", "rcpatroldisabled": "Recent changes patrol disabled", @@ -2725,6 +2726,7 @@ "newimages-legend": "Filter", "newimages-label": "Filename (or a part of it):", "newimages-showbots": "Show uploads by bots", + "newimages-hidepatrolled": "Hide patrolled uploads", "noimages": "Nothing to see.", "ilsubmit": "Search", "bydate": "by date", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index 34240d4..aac4582 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -2845,6 +2845,7 @@ "markaspatrolleddiff": "{{doc-actionlink}}\nSee also:\n* {{msg-mw|Markaspatrolledtext}}\n{{Identical|Mark as patrolled}}", "markaspatrolledlink": "{{notranslate}}\nParameters:\n* $1 - link which has text {{msg-mw|Markaspatrolledtext}}", "markaspatrolledtext": "{{doc-actionlink}}\nSee also:\n* {{msg-mw|Markaspatrolleddiff}}", + "markaspatrolledtext-file": "Same as markaspatrolledtext, but for files (new versions included) instead of pages.", "markedaspatrolled": "Used as title of the message {{msg-mw|Markedaspatrolledtext}}, when marking a change as patrolled.\n{{Related|Markedaspatrolled}}", "markedaspatrolledtext": "Used when marking a change as patrolled.\n\nThe title for this message is {{msg-mw|Markedaspatrolled}}.\n\nParameters:\n* $1 - page title\n{{Related|Markedaspatrolled}}", "rcpatroldisabled": "Used as title of the error message {{msg-mw|Rcpatroldisabledtext}}, when marking a change as patrolled.\n{{Related|Markedaspatrolled}}", @@ -2898,6 +2899,7 @@ "newimages-legend": "Caption of the fieldset for the filter on [[Special:NewImages]]\n\n{{Identical|Filter}}", "newimages-label": "Caption of the filter editbox on [[Special:NewImages]]", "newimages-showbots": "Used as label for a checkbox. When checked, [[Special:NewImages]] will also display uploads by users in the bots group.", + "newimages-hidepatrolled": "Used as label for a checkbox. When checked, [[Special:NewImages]] will not display patrolled uploads.", "noimages": "This is shown on the special page [[Special:NewImages]], when there aren't any recently uploaded files.", "ilsubmit": "Used as label for input box in the MIMESearch form on [[Special:MIMESearch]].\n\nSee also:\n* {{msg-mw|Mimesearch|page title}}\n* {{msg-mw|Mimetype|label for input box}}\n{{Identical|Search}}", "bydate": "{{Identical|Date}}", -- To view, visit https://gerrit.wikimedia.org/r/251795 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: If71af58719a4461f12d125455b7bef07164525ca Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: Cenarium <cenarium.sy...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits