aboutsummaryrefslogtreecommitdiffstats
path: root/includes/editpage
diff options
context:
space:
mode:
authorSomeRandomDeveloper <thisisnotmyname275@gmail.com>2024-11-12 20:55:39 +0100
committerSomeRandomDeveloper <thisisnotmyname275@gmail.com>2025-01-17 22:11:56 +0100
commit7dea105e52f286b163b599d4db2eb9f0629260ae (patch)
tree56bcbf7f44c5e01fea2cf472b3a8e04a1953e3d6 /includes/editpage
parent467c2d4f8065b016575963db3b65a5fc8aadf84e (diff)
downloadmediawikicore-7dea105e52f286b163b599d4db2eb9f0629260ae.tar.gz
mediawikicore-7dea105e52f286b163b599d4db2eb9f0629260ae.zip
Add a warning when trying to create a double redirect
Shows a warning when trying to create a redirect that points to another redirect. Bug: T326056 Change-Id: Ieb51dde88ce6c23753f74191a85cd40f0bfbd864
Diffstat (limited to 'includes/editpage')
-rw-r--r--includes/editpage/Constraint/DoubleRedirectConstraint.php104
-rw-r--r--includes/editpage/EditPage.php44
-rw-r--r--includes/editpage/IEditObject.php3
3 files changed, 151 insertions, 0 deletions
diff --git a/includes/editpage/Constraint/DoubleRedirectConstraint.php b/includes/editpage/Constraint/DoubleRedirectConstraint.php
new file mode 100644
index 000000000000..fd5ee1ab04cc
--- /dev/null
+++ b/includes/editpage/Constraint/DoubleRedirectConstraint.php
@@ -0,0 +1,104 @@
+<?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
+ */
+
+namespace MediaWiki\EditPage\Constraint;
+
+use MediaWiki\Content\Content;
+use MediaWiki\Linker\LinkTarget;
+use MediaWiki\Page\RedirectLookup;
+use MediaWiki\Title\Title;
+use StatusValue;
+
+/**
+ * Verify the page does not redirect to another redirect unless
+ * - the user is okay with a double redirect, or
+ * - the page already redirected to another redirect before the edit
+ *
+ * @since 1.44
+ * @internal
+ */
+class DoubleRedirectConstraint implements IEditConstraint {
+
+ private bool $allowDoubleRedirects;
+ private Content $newContent;
+ private Content $originalContent;
+ private LinkTarget $title;
+ private string $result;
+ private RedirectLookup $redirectLookup;
+
+ /**
+ * @param bool $allowDoubleRedirects
+ * @param Content $newContent
+ * @param Content $originalContent
+ * @param LinkTarget $title
+ */
+ public function __construct(
+ bool $allowDoubleRedirects,
+ Content $newContent,
+ Content $originalContent,
+ LinkTarget $title,
+ RedirectLookup $redirectLookup
+ ) {
+ $this->allowDoubleRedirects = $allowDoubleRedirects;
+ $this->newContent = $newContent;
+ $this->originalContent = $originalContent;
+ $this->title = $title;
+ $this->redirectLookup = $redirectLookup;
+ }
+
+ public function checkConstraint(): string {
+ if ( !$this->allowDoubleRedirects ) {
+ $newRedirectTarget = $this->newContent->getRedirectTarget();
+
+ if ( $newRedirectTarget !== null && $newRedirectTarget->isRedirect() &&
+ !$newRedirectTarget->equals( $this->title ) ) {
+
+ $currentTarget = $this->originalContent->getRedirectTarget();
+
+ // fail if there was no previous content or the previous content already contained a double redirect
+ if ( !$currentTarget || !$currentTarget->isRedirect() ) {
+ $this->result = self::CONSTRAINT_FAILED;
+
+ return self::CONSTRAINT_FAILED;
+ }
+ }
+ }
+ $this->result = self::CONSTRAINT_PASSED;
+
+ return self::CONSTRAINT_PASSED;
+ }
+
+ public function getLegacyStatus(): StatusValue {
+ $statusValue = StatusValue::newGood();
+ if ( $this->result === self::CONSTRAINT_FAILED ) {
+ $realRedirectTarget = $this->redirectLookup->getRedirectTarget( $this->newContent->getRedirectTarget() );
+ $realTargetTitle = Title::castFromLinkTarget( $realRedirectTarget );
+
+ $statusValue->fatal(
+ 'edit-constraint-doubleredirect',
+ wfEscapeWikiText( $realTargetTitle->getPrefixedText() )
+ );
+ $statusValue->value = self::AS_DOUBLE_REDIRECT;
+ }
+
+ return $statusValue;
+ }
+
+}
diff --git a/includes/editpage/EditPage.php b/includes/editpage/EditPage.php
index d492ce5a0b3c..b853e5d18067 100644
--- a/includes/editpage/EditPage.php
+++ b/includes/editpage/EditPage.php
@@ -45,6 +45,7 @@ use MediaWiki\EditPage\Constraint\BrokenRedirectConstraint;
use MediaWiki\EditPage\Constraint\ChangeTagsConstraint;
use MediaWiki\EditPage\Constraint\ContentModelChangeConstraint;
use MediaWiki\EditPage\Constraint\DefaultTextConstraint;
+use MediaWiki\EditPage\Constraint\DoubleRedirectConstraint;
use MediaWiki\EditPage\Constraint\EditConstraintFactory;
use MediaWiki\EditPage\Constraint\EditConstraintRunner;
use MediaWiki\EditPage\Constraint\EditFilterMergedContentHookConstraint;
@@ -269,6 +270,12 @@ class EditPage implements IEditObject {
/** @var bool */
private $allowBrokenRedirects = false;
+ /** @var bool */
+ private $doubleRedirect = false;
+
+ /** @var bool */
+ private $allowDoubleRedirects = false;
+
/** @var string */
private $autoSumm = '';
@@ -1327,6 +1334,7 @@ class EditPage implements IEditObject {
$this->allowBlankArticle = $request->getBool( 'wpIgnoreBlankArticle' );
$this->allowSelfRedirect = $request->getBool( 'wpIgnoreSelfRedirect' );
$this->allowBrokenRedirects = $request->getBool( 'wpIgnoreBrokenRedirects' );
+ $this->allowDoubleRedirects = $request->getBool( 'wpIgnoreDoubleRedirects' );
$changeTags = $request->getVal( 'wpChangeTags' );
if ( $changeTags === null || $changeTags === '' ) {
@@ -1860,6 +1868,7 @@ class EditPage implements IEditObject {
case self::AS_BLANK_ARTICLE:
case self::AS_SELF_REDIRECT:
case self::AS_BROKEN_REDIRECT:
+ case self::AS_DOUBLE_REDIRECT:
case self::AS_REVISION_WAS_DELETED:
return true;
@@ -2498,6 +2507,15 @@ class EditPage implements IEditObject {
)
);
$constraintRunner->addConstraint(
+ new DoubleRedirectConstraint(
+ $this->allowDoubleRedirects,
+ $content,
+ $this->getCurrentContent(),
+ $this->getTitle(),
+ $this->redirectLookup
+ )
+ );
+ $constraintRunner->addConstraint(
// Same constraint is used to check size before and after merging the
// edits, which use different failure codes
$constraintFactory->newPageSizeConstraint(
@@ -2619,6 +2637,8 @@ class EditPage implements IEditObject {
$this->selfRedirect = true;
} elseif ( $failed instanceof BrokenRedirectConstraint ) {
$this->brokenRedirect = true;
+ } elseif ( $failed instanceof DoubleRedirectConstraint ) {
+ $this->doubleRedirect = true;
}
}
@@ -3154,6 +3174,10 @@ class EditPage implements IEditObject {
$out->addHTML( Html::hidden( 'wpIgnoreBrokenRedirects', true ) );
}
+ if ( $this->doubleRedirect ) {
+ $out->addHTML( Html::hidden( 'wpIgnoreDoubleRedirects', true ) );
+ }
+
$autosumm = $this->autoSumm !== '' ? $this->autoSumm : md5( $this->summary );
$out->addHTML( Html::hidden( 'wpAutoSummary', $autosumm ) );
@@ -3374,6 +3398,26 @@ class EditPage implements IEditObject {
);
}
+ if ( $this->doubleRedirect ) {
+ $editContent = $this->toEditContent( $this->textbox1 );
+ $redirectTarget = $editContent->getRedirectTarget();
+
+ $doubleRedirectTarget = $this->redirectLookup->getRedirectTarget( $redirectTarget );
+ $doubleRedirectTargetTitle = Title::castFromLinkTarget( $doubleRedirectTarget );
+
+ $suggestedRedirectContent =
+ $editContent->getContentHandler()->makeRedirectContent( $doubleRedirectTargetTitle );
+ $suggestedRedirectCode =
+ Html::element( 'pre', [], $this->toEditText( $suggestedRedirectContent ) );
+
+ $out->wrapWikiMsg( "<div id='mw-doubleredirect'>\n$1\n</div>", [
+ 'edit-constraint-doubleredirect',
+ $buttonLabel,
+ wfEscapeWikiText( $doubleRedirectTargetTitle->getPrefixedText() ),
+ $suggestedRedirectCode,
+ ] );
+ }
+
if ( $this->hookError !== '' ) {
$out->addWikiTextAsInterface( $this->hookError );
}
diff --git a/includes/editpage/IEditObject.php b/includes/editpage/IEditObject.php
index 102377fcacf2..873f69f810ad 100644
--- a/includes/editpage/IEditObject.php
+++ b/includes/editpage/IEditObject.php
@@ -120,4 +120,7 @@ interface IEditObject {
/** Status: user tried to create a redirect to a nonexistent page and wpIgnoreBrokenRedirects is false */
public const AS_BROKEN_REDIRECT = 244;
+
+ /** Status: user tried to create a redirect to another redirect and wpIgnoreDoubleRedirects is false */
+ public const AS_DOUBLE_REDIRECT = 245;
}