Cenarium has uploaded a new change for review.

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

Change subject: Implement redirect-related and other tags in mediawiki core
......................................................................

Implement redirect-related and other tags in mediawiki core

This implements a class for tags defined and applied in core. This uses a
config variable consisting in an array of core tags with their 'active'
status (which determines whether they should be applied).
The already implemented content model change tag is integrated in this
framework. Along with it, the cross namespace move is active by default
but all others are inactive by default.

The list of tags implemented in this patch set is as follows:
        "tag-mw-move-crossnamespace": "Cross namespace move",
        "tag-mw-move-tomainspace": "Move to mainspace",
        "tag-mw-move-rename": "Move attempting rename",
        "tag-mw-redirect-new": "New redirect",
        "tag-mw-redirect-changed": "Changed redirect target",
        "tag-mw-redirect-self": "Self redirect",
        "tag-mw-redirect-nonexistent": "Redirect to nonexistent page",
        "tag-mw-redirect-removed": "Removed redirect",
        "tag-mw-edit-blank": "Edit blanking the page",
        "tag-mw-edit-replace": "Edit replaced the page content",
        "tag-mw-newpage-blank": "New page is blank".

They correspond to phabricator requests such as T14363 or T92621, to
tags commonly implemented as tag-only abuse filters on WMF wikis, or
to mediawiki autosummaries.

Bug: T73236
Change-Id: I365db826a6db062812d7b1c408cadcda37a677d5
---
M autoload.php
M includes/DefaultSettings.php
M includes/MovePage.php
M includes/changetags/ChangeTags.php
A includes/changetags/ChangeTagsCore.php
M includes/page/WikiPage.php
M languages/i18n/en.json
M languages/i18n/qqq.json
A tests/phpunit/includes/changetags/ChangeTagsCoreTest.php
9 files changed, 361 insertions(+), 15 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/83/311683/1

diff --git a/autoload.php b/autoload.php
index 716e56d..03de15c 100644
--- a/autoload.php
+++ b/autoload.php
@@ -224,6 +224,7 @@
        'CgzCopyTransaction' => __DIR__ . 
'/maintenance/storage/recompressTracked.php',
        'ChangePassword' => __DIR__ . '/maintenance/changePassword.php',
        'ChangeTags' => __DIR__ . '/includes/changetags/ChangeTags.php',
+       'ChangeTagsCore' => __DIR__ . '/includes/changetags/ChangeTagsCore.php',
        'ChangeTagsList' => __DIR__ . '/includes/changetags/ChangeTagsList.php',
        'ChangeTagsLogItem' => __DIR__ . 
'/includes/changetags/ChangeTagsLogItem.php',
        'ChangeTagsLogList' => __DIR__ . 
'/includes/changetags/ChangeTagsLogList.php',
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
index 135c3e5..91a65a2 100644
--- a/includes/DefaultSettings.php
+++ b/includes/DefaultSettings.php
@@ -6736,6 +6736,27 @@
 $wgUseTagFilter = true;
 
 /**
+ * List of automated tags defined in core with their 'active' status.
+ * To enable (resp. disable) automated tagging for a specific tag, set its
+ * active status to true (resp. false).
+ * @since 1.28
+ */
+$wgCoreTags = [
+       'mw-contentmodelchange' => [ 'active' => true ],
+       'mw-move-crossnamespace' => [ 'active' => true ],
+       'mw-move-tomainspace' => [ 'active' => false ],
+       'mw-move-rename' => [ 'active' => false ],
+       'mw-redirect-new' => [ 'active' => false ],
+       'mw-redirect-changed' => [ 'active' => false ],
+       'mw-redirect-self' => [ 'active' => false ],
+       'mw-redirect-nonexistent' => [ 'active' => false ],
+       'mw-redirect-removed' => [ 'active' => false ],
+       'mw-edit-blank' => [ 'active' => false ],
+       'mw-edit-replace' => [ 'active' => false ],
+       'mw-newpage-blank' => [ 'active' => false ],
+];
+
+/**
  * If set to an integer, pages that are watched by this many users or more
  * will not require the unwatchedpages permission to view the number of
  * watchers.
diff --git a/includes/MovePage.php b/includes/MovePage.php
index d17f234..e916f97 100644
--- a/includes/MovePage.php
+++ b/includes/MovePage.php
@@ -584,6 +584,15 @@
                        }
                }
 
+               // Associate rev id
+               $logEntry->setAssociatedRevId( $nullRevision->getId() );
+
+               // Apply tags if any
+               $autoTags = ChangeTagsCore::getAutotagsForMove( 
$this->oldTitle, $nt, $user );
+               if ( $autoTags ) {
+                       $logEntry->setTags( $autoTags );
+               }
+
                # Log the move
                $logid = $logEntry->insert();
                $logEntry->publish( $logid );
diff --git a/includes/changetags/ChangeTags.php 
b/includes/changetags/ChangeTags.php
index 3ef9641..db8575b 100644
--- a/includes/changetags/ChangeTags.php
+++ b/includes/changetags/ChangeTags.php
@@ -809,7 +809,8 @@
 
                // defined tags cannot be activated (a defined tag is either 
extension-
                // defined, in which case the extension chooses whether or not 
to active it;
-               // or user-defined, in which case it is considered active)
+               // or user-defined, in which case it is considered active, or 
core defined,
+               // in which case it is active or not according to the wiki 
settings)
                $definedTags = self::listDefinedTags();
                if ( in_array( $tag, $definedTags ) ) {
                        return Status::newFatal( 'tags-activate-not-allowed', 
$tag );
@@ -943,6 +944,12 @@
                // slashes (would break tag description messages in MediaWiki 
namespace)
                if ( strpos( $tag, ',' ) !== false || strpos( $tag, '/' ) !== 
false ) {
                        return Status::newFatal( 'tags-create-invalid-chars' );
+               }
+
+               // tags cannot contain some strings reserved for core tags, or 
system messages
+               if ( strpos( $tag, 'mw-' ) === 0 ||
+                       strpos( $tag, '-description' ) !== false ) {
+                       return Status::newFatal( 'tags-create-invalid-reserved' 
);
                }
 
                // could the MediaWiki namespace description messages be 
created?
@@ -1137,8 +1144,14 @@
         * @since 1.25
         */
        public static function listSoftwareActivatedTags() {
-               // core active tags
-               $tags = self::$coreTags;
+               global $wgCoreTags;
+               $tags = [];
+               foreach ( $wgCoreTags as $tag => $properties ) {
+                       // retrieve active core tags
+                       if ( $properties['active'] ) {
+                               $tags[] = $tag;
+                       }
+               }
                if ( !Hooks::isRegistered( 'ChangeTagsListActive' ) ) {
                        return $tags;
                }
@@ -1226,8 +1239,9 @@
         * @since 1.25
         */
        public static function listSoftwareDefinedTags() {
+               global $wgCoreTags;
                // core defined tags
-               $tags = self::$coreTags;
+               $tags = array_keys( $wgCoreTags );
                if ( !Hooks::isRegistered( 'ListDefinedTags' ) ) {
                        return $tags;
                }
diff --git a/includes/changetags/ChangeTagsCore.php 
b/includes/changetags/ChangeTagsCore.php
new file mode 100644
index 0000000..f0138fd
--- /dev/null
+++ b/includes/changetags/ChangeTagsCore.php
@@ -0,0 +1,174 @@
+<?php
+/**
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Change tagging
+ */
+
+/**
+ * Provides static methods to associate change tags defined in core to
+ * an edit or action presenting certain identifiable characteristics
+ * @since 1.28
+ */
+class ChangeTagsCore {
+
+       /**
+        * Return applicable autotags for an edit updating a page, if any.
+        * Based in part on getAutoSummaries from ContentHandler
+        *
+        * @since 1.28
+        *
+        * @param Content $oldContent The previous text of the page.
+        * @param Content $newContent The submitted text of the page.
+        * @param Title $pageTitle The title of the page whose content is being 
edited.
+        *
+        * @return array An array of tags, or an empty array.
+        */
+       public static function getAutotagsForEditUpdate( Content $oldContent, 
Content $newContent,
+               Title $pageTitle
+       ) {
+               $coreTags = RequestContext::getMain()->getConfig()->get( 
'CoreTags' );
+               $tags = [];
+
+               // content model change
+               if ( $coreTags['mw-contentmodelchange'] &&
+                       $oldContent->getModel() !== $newContent->getModel()
+               ) {
+                       $tags[] = 'mw-contentmodelchange';
+               }
+
+               // Redirect-related tags
+               // only extract redirect targets if at least one of these tags 
is in use
+               if ( $coreTags['mw-redirect-self']['active'] ||
+                       $coreTags['mw-redirect-nonexistent']['active'] ||
+                       $coreTags['mw-redirect-new']['active'] ||
+                       $coreTags['mw-redirect-changed']['active'] ||
+                       $coreTags['mw-redirect-removed']['active']
+               ) {
+                       $oldTarget = $oldContent->getRedirectTarget();
+                       $newTarget = $newContent->getRedirectTarget();
+                       if ( is_object( $newTarget ) ) {
+                               if ( $newTarget->equals( $pageTitle ) ) {
+                                       if ( 
$coreTags['mw-redirect-self']['active'] ) {
+                                               // page redirected to itself
+                                               $tags[] = 'mw-redirect-self';
+                                       }
+                               } elseif ( !$newTarget->exists() ) {
+                                       if ( 
$coreTags['mw-redirect-nonexistent']['active'] ) {
+                                               // redirected to non-existent 
page
+                                               $tags[] = 
'mw-redirect-nonexistent';
+                                       }
+                               }
+                               if ( !is_object( $oldTarget ) ) {
+                                       if ( 
$coreTags['mw-redirect-new']['active'] ) {
+                                               // non-redirect page gets 
redirected
+                                               $tags[] = 'mw-redirect-new';
+                                       }
+                               } elseif ( ( !$newTarget->equals( $oldTarget ) 
|| $oldTarget->getFragment()
+                                       != $newTarget->getFragment() )
+                               ) {
+                                       if ( 
$coreTags['mw-redirect-changed']['active'] ) {
+                                               // target of a redirect gets 
changed
+                                               $tags[] = 'mw-redirect-changed';
+                                       }
+                               }
+                       } elseif ( is_object( $oldTarget ) && 
$coreTags['mw-redirect-removed']['active'] ) { {
+                                       // redirect transformed in non-redirect 
page
+                                       $tags[] = 'mw-redirect-removed';
+                               }
+                       }
+               }
+
+               // Tags not related to redirects
+               if ( !empty( $oldContent ) && $oldContent->getSize() > 0 &&
+                       $newContent->getSize() == 0
+               ) {
+                       // edit blanked a non-blank page
+                       if ( $coreTags['mw-edit-blank']['active'] ) {
+                               $tags[] = 'mw-edit-blank';
+                       }
+               } elseif ( $coreTags['mw-edit-replace']['active'] && !empty( 
$oldContent )
+                       && $oldContent->getSize() > 10 * $newContent->getSize()
+                       && $newContent->getSize() < 500
+               ) {
+                       // edit replaced the page content
+                       $tags[] = 'mw-edit-replace';
+               }
+
+               return $tags;
+       }
+
+       /**
+        * Return applicable autotags for an edit creating a page, if any.
+        *
+        * @since 1.28
+        *
+        * @param Content $newContent The submitted text of the page.
+        * @param Title $pageTitle The title of the page whose content is being 
edited.
+        *
+        * @return array An array of tags, or an empty array.
+        */
+       public static function getAutotagsForEditNew( Content $newContent, 
Title $pageTitle ) {
+               $coreTags = RequestContext::getMain()->getConfig()->get( 
'CoreTags' );
+               $tags = [];
+
+               if ( $coreTags['mw-newpage-blank']['active'] && 
$newContent->getSize() == 0 ) {
+                       $tags[] = 'mw-newpage-blank';
+               }
+
+               return $tags;
+       }
+
+       /**
+        * Return applicable autotags for the given move, if any.
+        *
+        * @since 1.28
+        *
+        * @param Title $oldTitle The old title of the page.
+        * @param Title $newTitle The new title of the page.
+        * @param User $user The user performing the move.
+        *
+        * @return array An array of tags, or an empty array.
+        */
+       public static function getAutotagsForMove( Title $oldTitle, Title 
$newTitle, User $user ) {
+               $coreTags = RequestContext::getMain()->getConfig()->get( 
'CoreTags' );
+               $tags = [];
+
+               $oldNamespace = $oldTitle->getNamespace();
+               $newNamespace = $newTitle->getNamespace();
+               if ( $oldNamespace != $newNamespace ) {
+                       if ( $coreTags['mw-move-crossnamespace']['active'] ) {
+                               # cross namespace move
+                               $tags[] = 'mw-move-crossnamespace';
+                       }
+                       if ( $coreTags['mw-move-tomainspace']['active'] && 
$newNamespace == NS_MAIN ) {
+                               # move to mainspace
+                               $tags[] = 'mw-move-tomainspace';
+                       }
+               } elseif ( $coreTags['mw-move-rename']['active'] && 
$oldNamespace == NS_USER &&
+                       $newNamespace == NS_USER &&
+                       $oldTitle->getDBkey() == $user->getTitleKey() &&
+                       strpos( $newTitle->getDBkey(), '/' ) == false
+               ) {
+                       # user trying to rename
+                       $tags[] = 'mw-move-rename';
+               }
+
+               return $tags;
+       }
+}
diff --git a/includes/page/WikiPage.php b/includes/page/WikiPage.php
index faac26d..791f2c3 100644
--- a/includes/page/WikiPage.php
+++ b/includes/page/WikiPage.php
@@ -1691,10 +1691,6 @@
                $old_revision = $this->getRevision(); // current revision
                $old_content = $this->getContent( Revision::RAW ); // current 
revision's content
 
-               if ( $old_content && $old_content->getModel() !== 
$content->getModel() ) {
-                       $tags[] = 'mw-contentmodelchange';
-               }
-
                // Provide autosummaries if one is not provided and 
autosummaries are enabled
                if ( $wgUseAutomaticEditSummaries && ( $flags & 
EDIT_AUTOSUMMARY ) && $summary == '' ) {
                        $handler = $content->getContentHandler();
@@ -1722,7 +1718,7 @@
                        'oldId' => $this->getLatest(),
                        'oldIsRedirect' => $this->isRedirect(),
                        'oldCountable' => $this->isCountable(),
-                       'tags' => ( $tags !== null ) ? (array)$tags : []
+                       'tags' => $tags
                ];
 
                // Actually create the revision and create/update the page
@@ -1838,6 +1834,11 @@
                                // Mark as patrolled if the user can do so
                                $patrolled = $wgUseRCPatrol && !count(
                                                
$this->mTitle->getUserPermissionsErrors( 'autopatrol', $user ) );
+
+                               // Get autotags
+                               $autoTags = 
ChangeTagsCore::getAutotagsForEditUpdate( $oldContent, $content,
+                                       $this->mTitle );
+
                                // Add RC row to the DB
                                RecentChange::notifyEdit(
                                        $now,
@@ -1853,7 +1854,7 @@
                                        $newsize,
                                        $revisionId,
                                        $patrolled,
-                                       $meta['tags']
+                                       array_merge( $meta['tags'], $autoTags )
                                );
                        }
 
@@ -1986,6 +1987,10 @@
                        // Mark as patrolled if the user can do so
                        $patrolled = ( $wgUseRCPatrol || $wgUseNPPatrol ) &&
                                !count( 
$this->mTitle->getUserPermissionsErrors( 'autopatrol', $user ) );
+
+                       // Get autotags
+                       $autoTags = ChangeTagsCore::getAutotagsForEditNew( 
$content, $this->mTitle );
+
                        // Add RC row to the DB
                        RecentChange::notifyNew(
                                $now,
@@ -1998,7 +2003,7 @@
                                $newsize,
                                $revisionId,
                                $patrolled,
-                               $meta['tags']
+                               array_merge( $meta['tags'], $autoTags )
                        );
                }
 
diff --git a/languages/i18n/en.json b/languages/i18n/en.json
index a8dd103..51e6651 100644
--- a/languages/i18n/en.json
+++ b/languages/i18n/en.json
@@ -3663,8 +3663,30 @@
        "tag-filter": "[[Special:Tags|Tag]] filter:",
        "tag-filter-submit": "Filter",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Tag|Tags}}]]: $2)",
-       "tag-mw-contentmodelchange": "content model change",
-       "tag-mw-contentmodelchange-description": "Edits that 
[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel 
change the content model] of a page",
+       "tag-mw-contentmodelchange": "Content model change",
+       "tag-mw-move-tomainspace": "Move to mainspace",
+       "tag-mw-move-crossnamespace": "Cross namespace move",
+       "tag-mw-move-rename": "Rename attempt",
+       "tag-mw-redirect-new": "New redirect",
+       "tag-mw-redirect-changed": "Redirect changed",
+       "tag-mw-redirect-self": "Self redirect",
+       "tag-mw-redirect-nonexistent": "Redirect to nonexistent page",
+       "tag-mw-redirect-removed": "Redirect removal",
+       "tag-mw-edit-blank": "Page blanking",
+       "tag-mw-edit-replace": "Page content replaced",
+       "tag-mw-newpage-blank": "New blank page",
+       "tag-mw-contentmodelchange-description": "Automatically tagged as an 
edit that 
[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel 
changes the content model] of a page",
+       "tag-mw-move-tomainspace-description": "Automatically tagged as a move 
to [https://www.mediawiki.org/wiki/Help:Namespaces#.28Main.29 mainspace]",
+       "tag-mw-move-crossnamespace-description": "Automatically tagged as a 
move across [https://www.mediawiki.org/wiki/Help:Namespaces namespaces]",
+       "tag-mw-move-rename-description": "Automatically tagged as a move 
attempting a user rename",
+       "tag-mw-redirect-new-description": "Automatically tagged as an edit 
redirecting a non-redirect page",
+       "tag-mw-redirect-changed-description": "Automatically tagged as an edit 
changing the target of a redirect page",
+       "tag-mw-redirect-self-description": "Automatically tagged as an edit 
redirecting the page to itself",
+       "tag-mw-redirect-nonexistent-description": "Automatically tagged as an 
edit redirecting the page to a nonexistent page",
+       "tag-mw-redirect-removed-description": "Automatically tagged as an edit 
transforming a redirect page into a non-redirect page",
+       "tag-mw-edit-blank-description": "Automatically tagged as an edit 
blanking the page",
+       "tag-mw-edit-replace-description": "Automatically tagged as an edit 
replacing the page content",
+       "tag-mw-newpage-blank-description": "Automatically tagged as a page 
created blank",
        "tags-title": "Tags",
        "tags-intro": "This page lists the tags that the software may mark an 
edit with, and their meaning.",
        "tags-tag": "Tag name",
@@ -3693,6 +3715,7 @@
        "tags-create-submit": "Create",
        "tags-create-no-name": "You must specify a tag name.",
        "tags-create-invalid-chars": "Tag names must not contain commas 
(<code>,</code>) or forward slashes (<code>/</code>).",
+       "tags-create-invalid-reserved": "Tag names must not contain any of the 
following strings: <code>mw-</code> (at the beginning) or 
<code>-description</code> (anywhere).",
        "tags-create-invalid-title-chars": "Tag names must not contain 
characters that cannot be used in page titles.",
        "tags-create-already-exists": "The tag \"$1\" already exists.",
        "tags-create-warnings-above": "The following {{PLURAL:$2|warning 
was|warnings were}} encountered when attempting to create the tag \"$1\":",
diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json
index fbf95cc..7e2a8f1 100644
--- a/languages/i18n/qqq.json
+++ b/languages/i18n/qqq.json
@@ -3847,8 +3847,30 @@
        "tag-filter": "Caption of a filter shown on lists of changes (e.g. 
[[Special:Log]], [[Special:Contributions]], [[Special:Newpages]], 
[[Special:Recentchanges]], [[Special:Recentchangeslinked]], page histories)",
        "tag-filter-submit": "Caption of the submit button displayed next to 
the tag filter on lists of changes (e.g. [[Special:Log]], 
[[Special:Contributions]], [[Special:Newpages]], [[Special:Recentchanges]], 
[[Special:Recentchangeslinked]], page histories)\n\n{{Identical|Filter}}",
        "tag-list-wrapper": "Wrapper for the list of tags shown on recent 
changes, watchlists, history pages and diffs.\n\nParameters:\n* $1 - number of 
distinct tags for given edit\n* $2 - comma-separated list of tags for given 
edit",
-       "tag-mw-contentmodelchange": "Change tag for edits that change the 
content model of a page",
-       "tag-mw-contentmodelchange-description": "Description for \"content 
model change\" change tag",
+       "tag-mw-contentmodelchange": "Appearance next to edits or logs of the 
core tag for edits that change the content model of a page",
+       "tag-mw-move-tomainspace": "Appearance next to edits or logs of the 
core tag for moves to mainspace from another namespace",
+       "tag-mw-move-crossnamespace": "Appearance next to edits or logs of the 
core tag for cross namespace moves",
+       "tag-mw-move-rename": "Appearance next to edits or logs of the core tag 
for moves attempting to 'rename' the user",
+       "tag-mw-redirect-new": "Appearance next to edits or logs of the core 
tag for new redirects",
+       "tag-mw-redirect-changed": "Appearance next to edits or logs of the 
core tag for redirects whose target is changed",
+       "tag-mw-redirect-self": "Appearance next to edits or logs of the core 
tag for self-redirects",
+       "tag-mw-redirect-nonexistent": "Appearance next to edits or logs of the 
core tag for redirects to nonexistent pages",
+       "tag-mw-redirect-removed": "Appearance next to edits or logs of the 
core tag for redirects being removed",
+       "tag-mw-edit-blank": "Appearance next to edits or logs of the core tag 
for edits blanking the page",
+       "tag-mw-edit-replace": "Appearance next to edits or logs of the core 
tag for edits replacing the page content",
+       "tag-mw-newpage-blank": "Appearance next to edits or logs of the core 
tag for new pages created blank",
+       "tag-mw-contentmodelchange-description": "Description at Special:Tags 
of the core \"content model change\" change tag",
+       "tag-mw-move-tomainspace-description": "Description at Special:Tags of 
the core tag for moves to mainspace",
+       "tag-mw-move-crossnamespace-description": "Description at Special:Tags 
of the core tag for cross namespace moves",
+       "tag-mw-move-rename-description": "Description at Special:Tags of the 
core tag for moves attempting to 'rename' the user",
+       "tag-mw-redirect-new-description": "Description at Special:Tags of the 
core tag for new redirects",
+       "tag-mw-redirect-changed-description": "Description at Special:Tags of 
the core tag for redirects whose target is changed",
+       "tag-mw-redirect-self-description": "Description at Special:Tags of the 
core tag for self-redirects",
+       "tag-mw-redirect-nonexistent-description": "Description at Special:Tags 
of the core tag for redirects to nonexistent pages",
+       "tag-mw-redirect-removed-description": "Description at Special:Tags of 
the core tag for redirects being removed",
+       "tag-mw-edit-blank-description": "Description at Special:Tags of the 
core tag for edits blanking the page",
+       "tag-mw-edit-replace-description": "Description at Special:Tags of the 
core tag for edits replacing the page content",
+       "tag-mw-newpage-blank-description": "Description at Special:Tags of the 
core tag for new pages created blank",
        "tags-title": "The title of [[Special:Tags]].\n{{Identical|Tag}}",
        "tags-intro": "Explanation on top of [[Special:Tags]]. For more 
information on tags see [[mw:Manual:Tags|MediaWiki]].",
        "tags-tag": "Caption of a column in [[Special:Tags]]. For more 
information on tags see [[mw:Manual:Tags|MediaWiki]].",
@@ -3877,6 +3899,7 @@
        "tags-create-submit": "The label of the form \"submit\" button when the 
user is about to create a tag.\n{{Identical|Create}}",
        "tags-create-no-name": "Error message on [[Special:Tags]]",
        "tags-create-invalid-chars": "Error message on [[Special:Tags]]",
+       "tags-create-invalid-reserved": "Error message on [[Special:Tags]]",
        "tags-create-invalid-title-chars": "Error message on [[Special:Tags]]",
        "tags-create-already-exists": "Error message on [[Special:Tags]]",
        "tags-create-warnings-above": "Explanation placed before warning 
messages upon creating a tag.\n\nParameters:\n* $1 - the code name of the tag 
that the user is attempting to create\n* $2 - the number of warnings",
diff --git a/tests/phpunit/includes/changetags/ChangeTagsCoreTest.php 
b/tests/phpunit/includes/changetags/ChangeTagsCoreTest.php
new file mode 100644
index 0000000..2d0274c
--- /dev/null
+++ b/tests/phpunit/includes/changetags/ChangeTagsCoreTest.php
@@ -0,0 +1,76 @@
+<?php
+
+class ChangeTagsCoreTest extends MediaWikiTestCase {
+
+       protected function setUp() {
+               parent::setUp();
+               $this->setMwGlobals( [ 'wgCoreTags' => [
+                       'mw-contentmodelchange' => [ 'active' => true ],
+                       'mw-move-crossnamespace' => [ 'active' => true ],
+                       'mw-move-tomainspace' => [ 'active' => true ],
+                       'mw-move-rename' => [ 'active' => true ],
+                       'mw-redirect-new' => [ 'active' => true ],
+                       'mw-redirect-changed' => [ 'active' => true ],
+                       'mw-redirect-self' => [ 'active' => true ],
+                       'mw-redirect-nonexistent' => [ 'active' => true ],
+                       'mw-redirect-removed' => [ 'active' => true ],
+                       'mw-edit-blank' => [ 'active' => true ],
+                       'mw-edit-replace' => [ 'active' => true ],
+                       'mw-newpage-blank' => [ 'active' => true ],
+               ] ] );
+       }
+
+       /**
+        * @dataProvider provideGetAutotagsForEditUpdate
+        * @covers ChangeTagsCore::getAutotagsForEditUpdate
+        */
+       public function testGetAutotagsForEditUpdate( $oldText, $newText, 
$pageTitle, $expected ) {
+               $title = Title::makeTitle( NS_MAIN, $pageTitle );
+               $oldContent =  ContentHandler::makeContent( $oldText, null, 
CONTENT_MODEL_WIKITEXT );
+               $newContent =  ContentHandler::makeContent( $newText, null, 
CONTENT_MODEL_WIKITEXT );
+               $actual = ChangeTagsCore::getAutotagsForEditUpdate( 
$oldContent, $newContent, $title );
+
+               sort( $expected );
+               sort( $actual );
+               $this->assertEquals( $expected, $actual );
+       }
+
+       public function provideGetAutotagsForEditUpdate() {
+               return [
+                       [ 'Hi', '#REDIRECT [[Main Page]]', 'Main Page',
+                               [ 'mw-redirect-self', 'mw-redirect-new' ] ],
+                       [ '#REDIRECT [[Main Page]]', 'nothing', 'Some Page',
+                               [ 'mw-redirect-removed' ] ],
+                       [ 'Lorem ipsum', '', 'Some Page',
+                               [ 'mw-edit-blank' ] ],
+                       [ 'Lorem ipsum', 'Lorem ipsum dolor sit amet', 'Some 
Page',
+                               [] ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideGetAutotagsForMove
+        * @covers ChangeTagsCore::getAutotagsForMove
+        */
+       public function testGetAutotagsForMove(
+               $oldNs, $oldPage, $newNs, $newPage, $userName, $expected
+       ) {
+               $oldTitle = Title::makeTitle( $oldNs, $oldPage );
+               $newTitle = Title::makeTitle( $newNs, $newPage );
+               $user = User::newFromName( $userName );
+               $actual = ChangeTagsCore::getAutotagsForMove( $oldTitle, 
$newTitle, $user );
+
+               sort( $expected );
+               sort( $actual );
+               $this->assertEquals( $expected, $actual );
+       }
+
+       public function provideGetAutotagsForMove() {
+               return [
+                       [ NS_USER, 'John', NS_USER, 'James', 'John',
+                               [ 'mw-move-rename' ] ],
+                       [ NS_MAIN, 'Foo', NS_PROJECT, 'Foo', 'Caesar',
+                               [ 'mw-move-crossnamespace' ] ],
+               ];
+       }
+}

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I365db826a6db062812d7b1c408cadcda37a677d5
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

Reply via email to