Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
DoubleRedirectConstraint
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
3 / 3
11
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 checkConstraint
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
8
 getLegacyStatus
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21namespace MediaWiki\EditPage\Constraint;
22
23use MediaWiki\Content\Content;
24use MediaWiki\Linker\LinkTarget;
25use MediaWiki\Page\RedirectLookup;
26use MediaWiki\Title\Title;
27use StatusValue;
28
29/**
30 * Verify the page does not redirect to another redirect unless
31 *  - the user is okay with a double redirect, or
32 *  - the page already redirected to another redirect before the edit
33 *
34 * @since 1.44
35 * @internal
36 */
37class DoubleRedirectConstraint implements IEditConstraint {
38
39    private bool $allowDoubleRedirects;
40    private Content $newContent;
41    private Content $originalContent;
42    private LinkTarget $title;
43    private string $result;
44    public bool $willCreateSelfRedirect;
45    private ?LinkTarget $doubleRedirectTarget;
46    private RedirectLookup $redirectLookup;
47
48    /**
49     * @param bool $allowDoubleRedirects
50     * @param Content $newContent
51     * @param Content $originalContent
52     * @param LinkTarget $title
53     * @param RedirectLookup $redirectLookup
54     */
55    public function __construct(
56        bool $allowDoubleRedirects,
57        Content $newContent,
58        Content $originalContent,
59        LinkTarget $title,
60        RedirectLookup $redirectLookup
61    ) {
62        $this->allowDoubleRedirects = $allowDoubleRedirects;
63        $this->newContent = $newContent;
64        $this->originalContent = $originalContent;
65        $this->title = $title;
66        $this->redirectLookup = $redirectLookup;
67    }
68
69    public function checkConstraint(): string {
70        if ( !$this->allowDoubleRedirects ) {
71            $newRedirectTarget = $this->newContent->getRedirectTarget();
72
73            if ( $newRedirectTarget !== null && $newRedirectTarget->isRedirect() &&
74                !$newRedirectTarget->equals( $this->title ) ) {
75
76                $currentTarget = $this->originalContent->getRedirectTarget();
77
78                // fail if there was no previous content or the previous content already contained a double redirect
79                if ( !$currentTarget || !$currentTarget->isRedirect() ) {
80                    $this->result = self::CONSTRAINT_FAILED;
81                    $this->doubleRedirectTarget =
82                        $this->redirectLookup->getRedirectTarget( $this->newContent->getRedirectTarget() );
83                    $this->willCreateSelfRedirect =
84                        $this->doubleRedirectTarget != null &&
85                        $this->doubleRedirectTarget->isSameLinkAs( $this->title );
86
87                    return self::CONSTRAINT_FAILED;
88                }
89            }
90        }
91        $this->result = self::CONSTRAINT_PASSED;
92
93        return self::CONSTRAINT_PASSED;
94    }
95
96    public function getLegacyStatus(): StatusValue {
97        $statusValue = StatusValue::newGood();
98        if ( $this->result === self::CONSTRAINT_FAILED ) {
99            $realRedirectTarget = $this->redirectLookup->getRedirectTarget( $this->newContent->getRedirectTarget() );
100            $realTargetTitle = Title::castFromLinkTarget( $realRedirectTarget );
101
102            $statusValue->fatal(
103                'edit-constraint-doubleredirect',
104                wfEscapeWikiText( $realTargetTitle->getPrefixedText() )
105            );
106            $statusValue->value = self::AS_DOUBLE_REDIRECT;
107        }
108
109        return $statusValue;
110    }
111
112}