Addshore has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/273894

Change subject: WIP DMN CatWatch noinclude includeonly tags
......................................................................

WIP DMN CatWatch noinclude includeonly tags

Bug: T126139
Change-Id: I2552005f537cd57defb07574b8577cda933cbaf7
---
M includes/changes/CategoryMembershipChange.php
M includes/jobqueue/jobs/CategoryMembershipChangeJob.php
M languages/i18n/en.json
M languages/i18n/qqq.json
4 files changed, 139 insertions(+), 39 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/94/273894/3

diff --git a/includes/changes/CategoryMembershipChange.php 
b/includes/changes/CategoryMembershipChange.php
index 1ff6f85..cf9cd83d 100644
--- a/includes/changes/CategoryMembershipChange.php
+++ b/includes/changes/CategoryMembershipChange.php
@@ -30,6 +30,10 @@
        const CATEGORY_ADDITION = 1;
        const CATEGORY_REMOVAL = -1;
 
+       const CATEGORY_NORMAL = 0;
+       const CATEGORY_NO_INCLUDE = 1;
+       const CATEGORY_INCLUDE_ONLY = 2;
+
        /**
         * @var string Current timestamp, set during 
CategoryMembershipChange::__construct()
         */
@@ -102,35 +106,35 @@
         * Create a recentchanges entry for category additions
         *
         * @param Title $categoryTitle
+        * @param int $type
         */
-       public function triggerCategoryAddedNotification( Title $categoryTitle 
) {
-               $this->createRecentChangesEntry( $categoryTitle, 
self::CATEGORY_ADDITION );
+       public function triggerCategoryAddedNotification( Title $categoryTitle, 
$type ) {
+               $this->createRecentChangesEntry( $categoryTitle, 
self::CATEGORY_ADDITION, $type );
        }
 
        /**
         * Create a recentchanges entry for category removals
         *
         * @param Title $categoryTitle
+        * @param int $type
         */
-       public function triggerCategoryRemovedNotification( Title 
$categoryTitle ) {
-               $this->createRecentChangesEntry( $categoryTitle, 
self::CATEGORY_REMOVAL );
+       public function triggerCategoryRemovedNotification( Title 
$categoryTitle, $type ) {
+               $this->createRecentChangesEntry( $categoryTitle, 
self::CATEGORY_REMOVAL, $type );
        }
 
        /**
         * Create a recentchanges entry using 
RecentChange::notifyCategorization()
         *
         * @param Title $categoryTitle
+        * @param int $addedOrRemoved
         * @param int $type
         */
-       private function createRecentChangesEntry( Title $categoryTitle, $type 
) {
+       private function createRecentChangesEntry( Title $categoryTitle, 
$addedOrRemoved, $type ) {
                $this->notifyCategorization(
                        $this->timestamp,
                        $categoryTitle,
                        $this->getUser(),
-                       $this->getChangeMessageText( $type, [
-                               'prefixedText' => 
$this->pageTitle->getPrefixedText(),
-                               'numTemplateLinks' => $this->numTemplateLinks
-                       ] ),
+                       $this->getChangeMessageText( $addedOrRemoved, $type ),
                        $this->pageTitle,
                        $this->getPreviousRevisionTimestamp(),
                        $this->revision
@@ -239,25 +243,34 @@
         * The message keys created in this method may be one of:
         * - recentchanges-page-added-to-category
         * - recentchanges-page-added-to-category-bundled
+        * - recentchanges-page-added-to-category-transcluded
         * - recentchanges-page-removed-from-category
         * - recentchanges-page-removed-from-category-bundled
+        * - recentchanges-page-removed-from-category-transcluded
         *
-        * @param int $type may be CategoryMembershipChange::CATEGORY_ADDITION
+        * @param int $addedOrRemoved may be 
CategoryMembershipChange::CATEGORY_ADDITION
         * or CategoryMembershipChange::CATEGORY_REMOVAL
-        * @param array $params
-        * - prefixedText: result of Title::->getPrefixedText()
+        * @param int $type may be CategoryMembershipChange::CATEGORY_NORMAL
+        * or CategoryMembershipChange::CATEGORY_NO_INCLUDE or 
CategoryMembershipChange::CATEGORY_INCLUDE_ONLY
         *
         * @return string
         */
-       private function getChangeMessageText( $type, array $params ) {
+       private function getChangeMessageText( $addedOrRemoved, $type ) {
+               $params = [
+                       'prefixedText' => $this->pageTitle->getPrefixedText(),
+                       'numTemplateLinks' => $this->numTemplateLinks,
+               ];
+
                $array = [
                        self::CATEGORY_ADDITION => 
'recentchanges-page-added-to-category',
                        self::CATEGORY_REMOVAL => 
'recentchanges-page-removed-from-category',
                ];
 
-               $msgKey = $array[$type];
+               $msgKey = $array[$addedOrRemoved];
 
-               if ( intval( $params['numTemplateLinks'] ) > 0 ) {
+               if ( $type == self::CATEGORY_INCLUDE_ONLY ) {
+                       $msgKey .= '-transcluded';
+               } elseif ( $type != self::CATEGORY_NO_INCLUDE && intval( 
$params['numTemplateLinks'] ) > 0 ) {
                        $msgKey .= '-bundled';
                }
 
diff --git a/includes/jobqueue/jobs/CategoryMembershipChangeJob.php 
b/includes/jobqueue/jobs/CategoryMembershipChangeJob.php
index 57e69b4..45feed3 100644
--- a/includes/jobqueue/jobs/CategoryMembershipChangeJob.php
+++ b/includes/jobqueue/jobs/CategoryMembershipChangeJob.php
@@ -150,9 +150,17 @@
                }
 
                // Parse the new revision and get the categories
-               $categoryChanges = $this->getExplicitCategoriesChanges( $title, 
$newRev, $oldRev );
-               list( $categoryInserts, $categoryDeletes ) = $categoryChanges;
-               if ( !$categoryInserts && !$categoryDeletes ) {
+               $categoryChangesMap = $this->getExplicitCategoriesChanges( 
$title, $newRev, $oldRev );
+
+               $nothingToDo = true;
+               foreach ( $categoryChangesMap as $levelOne ) {
+                       foreach ( $levelOne as $levelTwo ) {
+                               if ( $levelTwo ) {
+                                       $nothingToDo = false;
+                               }
+                       }
+               }
+               if ( $nothingToDo ) {
                        return; // nothing to do
                }
 
@@ -163,21 +171,25 @@
                $batchSize = $config->get( 'UpdateRowsPerQuery' );
                $insertCount = 0;
 
-               foreach ( $categoryInserts as $categoryName ) {
-                       $categoryTitle = Title::makeTitle( NS_CATEGORY, 
$categoryName );
-                       $catMembChange->triggerCategoryAddedNotification( 
$categoryTitle );
-                       if ( $insertCount++ && ( $insertCount % $batchSize ) == 
0 ) {
-                               $dbw->commit( __METHOD__, 'flush' );
-                               wfGetLBFactory()->waitForReplication();
+               foreach ( 
$categoryChangesMap[CategoryMembershipChange::CATEGORY_ADDITION] as $type => 
$categoryListMap ) {
+                       foreach( $categoryListMap as $categoryName ) {
+                               $categoryTitle = Title::makeTitle( NS_CATEGORY, 
$categoryName );
+                               
$catMembChange->triggerCategoryAddedNotification( $categoryTitle, $type );
+                               if ( $insertCount++ && ( $insertCount % 
$batchSize ) == 0 ) {
+                                       $dbw->commit( __METHOD__, 'flush' );
+                                       wfGetLBFactory()->waitForReplication();
+                               }
                        }
                }
 
-               foreach ( $categoryDeletes as $categoryName ) {
-                       $categoryTitle = Title::makeTitle( NS_CATEGORY, 
$categoryName );
-                       $catMembChange->triggerCategoryRemovedNotification( 
$categoryTitle );
-                       if ( $insertCount++ && ( $insertCount++ % $batchSize ) 
== 0 ) {
-                               $dbw->commit( __METHOD__, 'flush' );
-                               wfGetLBFactory()->waitForReplication();
+               foreach ( 
$categoryChangesMap[CategoryMembershipChange::CATEGORY_REMOVAL] as $type => 
$categoryListMap ) {
+                       foreach( $categoryListMap as $categoryName ) {
+                               $categoryTitle = Title::makeTitle( NS_CATEGORY, 
$categoryName );
+                               
$catMembChange->triggerCategoryRemovedNotification( $categoryTitle, $type );
+                               if ( $insertCount++ && ( $insertCount++ % 
$batchSize ) == 0 ) {
+                                       $dbw->commit( __METHOD__, 'flush' );
+                                       wfGetLBFactory()->waitForReplication();
+                               }
                        }
                }
        }
@@ -192,16 +204,42 @@
                // Parse the old rev and get the categories. Do not use link 
tables as that
                // assumes these updates are perfectly FIFO and that link 
tables are always
                // up to date, neither of which are true.
-               $oldCategories = $oldRev
+               $oldCats = $oldRev
                        ? $this->getCategoriesAtRev( $title, $oldRev, 
$parseTimestamp )
                        : [];
+               $oldCatsWhenTranscluded = $oldRev
+                       ? $this->getCategoriesWhenTranscluded( $title, $oldRev, 
$parseTimestamp )
+                       : [];
                // Parse the new revision and get the categories
-               $newCategories = $this->getCategoriesAtRev( $title, $newRev, 
$parseTimestamp );
+               $newCats = $this->getCategoriesAtRev( $title, $newRev, 
$parseTimestamp );
+               $newCatsWhenTranscluded = $this->getCategoriesWhenTranscluded( 
$title, $newRev, $parseTimestamp );
 
-               $categoryInserts = array_values( array_diff( $newCategories, 
$oldCategories ) );
-               $categoryDeletes = array_values( array_diff( $oldCategories, 
$newCategories ) );
+               $newCatsNoInclude = array_values( array_diff( $newCats, 
$newCatsWhenTranscluded ) );
+               $newCatsIncludeOnly = array_values( array_diff( 
$newCatsWhenTranscluded, $newCats ) );
+               $newCatsNormalText = array_values( array_diff( $newCats, 
array_merge( $newCatsNoInclude, $newCatsIncludeOnly ) ) );
 
-               return [ $categoryInserts, $categoryDeletes ];
+               $oldCatsNoInclude = array_values( array_diff( $oldCats, 
$oldCatsWhenTranscluded ) );
+               $oldCatsIncludeOnly = array_values( array_diff( 
$oldCatsWhenTranscluded, $oldCats ) );
+               $oldCatsNormalText = array_values( array_diff( $oldCats, 
array_merge( $oldCatsNoInclude, $oldCatsIncludeOnly ) ) );
+
+               return [
+                       CategoryMembershipChange::CATEGORY_ADDITION => [
+                               CategoryMembershipChange::CATEGORY_NORMAL =>
+                                       array_values( array_diff( 
$newCatsNormalText, $oldCatsNormalText ) ),
+                               CategoryMembershipChange::CATEGORY_INCLUDE_ONLY 
=>
+                                       array_values( array_diff( 
$newCatsIncludeOnly, $oldCatsIncludeOnly ) ),
+                               CategoryMembershipChange::CATEGORY_NO_INCLUDE =>
+                                       array_values( array_diff( 
$newCatsNoInclude, $oldCatsNoInclude ) ),
+                       ],
+                       CategoryMembershipChange::CATEGORY_REMOVAL => [
+                               CategoryMembershipChange::CATEGORY_NORMAL =>
+                                       array_values( array_diff( 
$oldCatsNormalText, $newCatsNormalText ) ),
+                               CategoryMembershipChange::CATEGORY_INCLUDE_ONLY 
=>
+                                       array_values( array_diff( 
$oldCatsIncludeOnly, $newCatsIncludeOnly ) ),
+                               CategoryMembershipChange::CATEGORY_NO_INCLUDE =>
+                                       array_values( array_diff( 
$oldCatsNoInclude, $newCatsNoInclude ) ),
+                       ],
+               ];
        }
 
        /**
@@ -213,10 +251,7 @@
         */
        private function getCategoriesAtRev( Title $title, Revision $rev, 
$parseTimestamp ) {
                $content = $rev->getContent();
-               $options = $content->getContentHandler()->makeParserOptions( 
'canonical' );
-               $options->setTimestamp( $parseTimestamp );
-               // This could possibly use the parser cache if it checked the 
revision ID,
-               // but that's more complicated than it's worth.
+               $options = $this->getParserOptions( $content, $parseTimestamp );
                $output = $content->getParserOutput( $title, $rev->getId(), 
$options );
 
                // array keys will cast numeric category names to ints
@@ -224,6 +259,54 @@
                return array_map( 'strval', array_keys( 
$output->getCategories() ) );
        }
 
+       /**
+        * Gets a list of categories when the title is included on another page.
+        * Thus this includes categories in <includeonly> tags but not 
categories in <noinclude> tags
+        *
+        * @param Title $title
+        * @param Revision $rev
+        * @param string $parseTimestamp TS_MW
+        *
+        * @return string[] category names
+        */
+       private function getCategoriesWhenTranscluded( Title $title, Revision 
$rev, $parseTimestamp ) {
+               global $wgHooks;
+
+               $content = $rev->getContent();
+               if ( $content->getModel() != CONTENT_MODEL_WIKITEXT ) {
+                       return [];
+               }
+
+               $wgHooks['BeforeParserFetchTemplateAndtitle'][__METHOD__] = 
function (
+                       Parser $parser,
+                       Title $title,
+                       &$skip,
+                       &$id
+               ) use ( $rev ) {
+                       $id = $rev->getId();
+                       return true;
+               };
+
+               $content = new WikitextContent( '{{:' . 
$title->getPrefixedText() . '}}' );
+               $options = $this->getParserOptions( $content, $parseTimestamp );
+               $output = $content->getParserOutput( $title, $rev->getId(), 
$options );
+
+               unset( 
$wgHooks['BeforeParserFetchTemplateAndtitle'][__METHOD__] );
+
+               // array keys will cast numeric category names to ints
+               // so we need to cast them back to strings to avoid breaking 
things!
+               return array_map( 'strval', array_keys( 
$output->getCategories() ) );
+       }
+
+       private function getParserOptions( Content $content, $parseTimestamp ) {
+               $options = $content->getContentHandler()->makeParserOptions( 
'canonical' );
+               // This could possibly use the parser cache if it checked the 
revision ID,
+               // but that's more complicated than it's worth.
+               $options->setTimestamp( $parseTimestamp );
+
+               return $options;
+       }
+
        public function getDeduplicationInfo() {
                $info = parent::getDeduplicationInfo();
                unset( $info['params']['revTimestamp'] ); // first job wins
diff --git a/languages/i18n/en.json b/languages/i18n/en.json
index 2b83ff6..13f7b56 100644
--- a/languages/i18n/en.json
+++ b/languages/i18n/en.json
@@ -1378,8 +1378,10 @@
        "recentchangeslinked-to": "Show changes to pages linked to the given 
page instead",
        "recentchanges-page-added-to-category": "[[:$1]] added to category",
        "recentchanges-page-added-to-category-bundled": "[[:$1]] and 
{{PLURAL:$2|one page|$2 pages}} added to category",
+       "recentchanges-page-added-to-category-transcluded": "{{PLURAL:$2|one 
page|$2 pages}} transcluding [[:$1]] added to category",
        "recentchanges-page-removed-from-category": "[[:$1]] removed from 
category",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] and 
{{PLURAL:$2|one page|$2 pages}} removed from category",
+       "recentchanges-page-removed-to-category-transcluded": "{{PLURAL:$2|one 
page|$2 pages}} transcluding [[:$1]] removed from category",
        "autochange-username": "MediaWiki automatic change",
        "upload": "Upload file",
        "uploadbtn": "Upload file",
diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json
index 5d8762d..e4dc7cf 100644
--- a/languages/i18n/qqq.json
+++ b/languages/i18n/qqq.json
@@ -1554,8 +1554,10 @@
        "recentchangeslinked-to": "Checkbox in 
[[Special:RecentChangesLinked]].",
        "recentchanges-page-added-to-category": "Comment message for pages 
added to a category\n\nParameters:\n* $1 - name of the page being added",
        "recentchanges-page-added-to-category-bundled": "Comment message for 
template embedded by other pages added to a category\n\nParameters:\n* $1 - 
name of the page being added\n* $2 - number of additional pages being affected",
+       "recentchanges-page-added-to-category-transcluded": "Comment message 
for template embedded by other pages added to a category when the category is 
not added to the template itself\n\nParameters:\n* $1 - name of the template 
page\n* $2 - number of additional pages being affected",
        "recentchanges-page-removed-from-category": "Comment message for pages 
removed from a category\n\nParameters:\n* $1 - name of the page being removed",
        "recentchanges-page-removed-from-category-bundled": "Comment message 
for templates embeddedby other pages removed from a category\n\nParameters:\n* 
$1 - name of the page being added\n* $2 - number of additional pages being 
affected",
+       "recentchanges-page-removed-from-category-transcluded": "Comment 
message for templates embeddedby other pages removed from a category when the 
category is not removed from the template itself\n\nParameters:\n* $1 - name of 
the template page\n* $2 - number of additional pages being affected",
        "autochange-username": "Used as bot / unknown username.",
        "upload": "Display name for link to [[Special:Upload]] for uploading 
files to the wiki.\n\nSee also:\n* {{msg-mw|Upload}}\n* 
{{msg-mw|Accesskey-t-upload}}\n* 
{{msg-mw|Tooltip-t-upload}}\n{{Identical|Upload file}}",
        "uploadbtn": "Button name in [[Special:Upload]].\n\nSee also:\n* 
{{msg-mw|Uploadbtn}}\n* {{msg-mw|Accesskey-upload}}\n* 
{{msg-mw|Tooltip-upload}}\n{{Identical|Upload file}}",

-- 
To view, visit https://gerrit.wikimedia.org/r/273894
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I2552005f537cd57defb07574b8577cda933cbaf7
Gerrit-PatchSet: 3
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Addshore <[email protected]>
Gerrit-Reviewer: Aaron Schulz <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: WMDE-Fisch <[email protected]>
Gerrit-Reviewer: WMDE-leszek <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to