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