Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 86
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialComparePages
0.00% covered (danger)
0.00%
0 / 85
0.00% covered (danger)
0.00%
0 / 6
210
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 54
0.00% covered (danger)
0.00%
0 / 1
6
 showDiff
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
12
 revOrTitle
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 checkExistingRevision
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Copyright © 2010 Derk-Jan Hartman <hartman@videolan.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 */
22
23namespace MediaWiki\Specials;
24
25use DifferenceEngine;
26use MediaWiki\Content\IContentHandlerFactory;
27use MediaWiki\HTMLForm\HTMLForm;
28use MediaWiki\Revision\RevisionLookup;
29use MediaWiki\Revision\RevisionRecord;
30use MediaWiki\Revision\SlotRecord;
31use MediaWiki\SpecialPage\SpecialPage;
32use MediaWiki\Title\Title;
33
34/**
35 * Implements Special:ComparePages
36 *
37 * @ingroup SpecialPage
38 */
39class SpecialComparePages extends SpecialPage {
40
41    private RevisionLookup $revisionLookup;
42    private IContentHandlerFactory $contentHandlerFactory;
43
44    /** @var DifferenceEngine */
45    private $differenceEngine;
46
47    public function __construct(
48        RevisionLookup $revisionLookup,
49        IContentHandlerFactory $contentHandlerFactory
50    ) {
51        parent::__construct( 'ComparePages' );
52        $this->revisionLookup = $revisionLookup;
53        $this->contentHandlerFactory = $contentHandlerFactory;
54    }
55
56    /**
57     * Show a form for filtering namespace and username
58     *
59     * @param string|null $par
60     */
61    public function execute( $par ) {
62        $this->setHeaders();
63        $this->outputHeader();
64        $this->getOutput()->addModuleStyles( 'mediawiki.special' );
65        $this->addHelpLink( 'Help:Diff' );
66
67        $form = HTMLForm::factory( 'ooui', [
68            'Page1' => [
69                'type' => 'title',
70                'exists' => true,
71                'name' => 'page1',
72                'label-message' => 'compare-page1',
73                'size' => '40',
74                'section' => 'page1',
75                'required' => false,
76            ],
77            'Revision1' => [
78                'type' => 'int',
79                'name' => 'rev1',
80                'label-message' => 'compare-rev1',
81                'size' => '8',
82                'section' => 'page1',
83                'validation-callback' => [ $this, 'checkExistingRevision' ],
84            ],
85            'Page2' => [
86                'type' => 'title',
87                'name' => 'page2',
88                'exists' => true,
89                'label-message' => 'compare-page2',
90                'size' => '40',
91                'section' => 'page2',
92                'required' => false,
93            ],
94            'Revision2' => [
95                'type' => 'int',
96                'name' => 'rev2',
97                'label-message' => 'compare-rev2',
98                'size' => '8',
99                'section' => 'page2',
100                'validation-callback' => [ $this, 'checkExistingRevision' ],
101            ],
102            'Action' => [
103                'type' => 'hidden',
104                'name' => 'action',
105            ],
106            'Unhide' => [
107                'type' => 'hidden',
108                'name' => 'unhide',
109            ],
110        ], $this->getContext(), 'compare' );
111
112        $form->setMethod( 'get' )
113            ->setSubmitTextMsg( 'compare-submit' )
114            ->setSubmitCallback( [ $this, 'showDiff' ] )
115            ->show();
116
117        if ( $this->differenceEngine ) {
118            $this->differenceEngine->showDiffPage( true );
119        }
120    }
121
122    /**
123     * @internal Callback for HTMLForm
124     * @param array $data
125     * @param HTMLForm $form
126     */
127    public function showDiff( $data, HTMLForm $form ) {
128        $rev1 = $this->revOrTitle( $data['Revision1'], $data['Page1'] );
129        $rev2 = $this->revOrTitle( $data['Revision2'], $data['Page2'] );
130
131        if ( $rev1 && $rev2 ) {
132            // Revision IDs either passed the existence check or were fetched from existing titles.
133            $revisionRecord = $this->revisionLookup->getRevisionById( $rev1 );
134            $contentModel = $revisionRecord->getSlot(
135                SlotRecord::MAIN,
136                RevisionRecord::RAW
137            )->getModel();
138            $contentHandler = $this->contentHandlerFactory->getContentHandler( $contentModel );
139            $this->differenceEngine = $contentHandler->createDifferenceEngine( $form->getContext(),
140                $rev1,
141                $rev2,
142                0, // rcid
143                ( $data['Action'] == 'purge' ),
144                ( $data['Unhide'] == '1' )
145            );
146        }
147    }
148
149    private function revOrTitle( $revision, $title ) {
150        if ( $revision ) {
151            return $revision;
152        } elseif ( $title ) {
153            return Title::newFromText( $title )->getLatestRevID();
154        }
155
156        return null;
157    }
158
159    /**
160     * @internal Callback for HTMLForm
161     * @param string|null $value
162     * @param array $alldata
163     * @return string|bool
164     */
165    public function checkExistingRevision( $value, $alldata ) {
166        if ( $value === '' || $value === null ) {
167            return true;
168        }
169        $revisionRecord = $this->revisionLookup->getRevisionById( (int)$value );
170        if ( $revisionRecord === null ) {
171            return $this->msg( 'compare-revision-not-exists' )->parseAsBlock();
172        }
173
174        return true;
175    }
176
177    protected function getGroupName() {
178        return 'pagetools';
179    }
180}
181
182/** @deprecated class alias since 1.41 */
183class_alias( SpecialComparePages::class, 'SpecialComparePages' );