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    /**
48     * @param RevisionLookup $revisionLookup
49     * @param IContentHandlerFactory $contentHandlerFactory
50     */
51    public function __construct(
52        RevisionLookup $revisionLookup,
53        IContentHandlerFactory $contentHandlerFactory
54    ) {
55        parent::__construct( 'ComparePages' );
56        $this->revisionLookup = $revisionLookup;
57        $this->contentHandlerFactory = $contentHandlerFactory;
58    }
59
60    /**
61     * Show a form for filtering namespace and username
62     *
63     * @param string|null $par
64     */
65    public function execute( $par ) {
66        $this->setHeaders();
67        $this->outputHeader();
68        $this->getOutput()->addModuleStyles( 'mediawiki.special' );
69        $this->addHelpLink( 'Help:Diff' );
70
71        $form = HTMLForm::factory( 'ooui', [
72            'Page1' => [
73                'type' => 'title',
74                'exists' => true,
75                'name' => 'page1',
76                'label-message' => 'compare-page1',
77                'size' => '40',
78                'section' => 'page1',
79                'required' => false,
80            ],
81            'Revision1' => [
82                'type' => 'int',
83                'name' => 'rev1',
84                'label-message' => 'compare-rev1',
85                'size' => '8',
86                'section' => 'page1',
87                'validation-callback' => [ $this, 'checkExistingRevision' ],
88            ],
89            'Page2' => [
90                'type' => 'title',
91                'name' => 'page2',
92                'exists' => true,
93                'label-message' => 'compare-page2',
94                'size' => '40',
95                'section' => 'page2',
96                'required' => false,
97            ],
98            'Revision2' => [
99                'type' => 'int',
100                'name' => 'rev2',
101                'label-message' => 'compare-rev2',
102                'size' => '8',
103                'section' => 'page2',
104                'validation-callback' => [ $this, 'checkExistingRevision' ],
105            ],
106            'Action' => [
107                'type' => 'hidden',
108                'name' => 'action',
109            ],
110            'Unhide' => [
111                'type' => 'hidden',
112                'name' => 'unhide',
113            ],
114        ], $this->getContext(), 'compare' );
115
116        $form->setMethod( 'get' )
117            ->setSubmitTextMsg( 'compare-submit' )
118            ->setSubmitCallback( [ $this, 'showDiff' ] )
119            ->show();
120
121        if ( $this->differenceEngine ) {
122            $this->differenceEngine->showDiffPage( true );
123        }
124    }
125
126    /**
127     * @internal Callback for HTMLForm
128     * @param array $data
129     * @param HTMLForm $form
130     */
131    public function showDiff( $data, HTMLForm $form ) {
132        $rev1 = $this->revOrTitle( $data['Revision1'], $data['Page1'] );
133        $rev2 = $this->revOrTitle( $data['Revision2'], $data['Page2'] );
134
135        if ( $rev1 && $rev2 ) {
136            // Revision IDs either passed the existence check or were fetched from existing titles.
137            $revisionRecord = $this->revisionLookup->getRevisionById( $rev1 );
138            $contentModel = $revisionRecord->getSlot(
139                SlotRecord::MAIN,
140                RevisionRecord::RAW
141            )->getModel();
142            $contentHandler = $this->contentHandlerFactory->getContentHandler( $contentModel );
143            $this->differenceEngine = $contentHandler->createDifferenceEngine( $form->getContext(),
144                $rev1,
145                $rev2,
146                0, // rcid
147                ( $data['Action'] == 'purge' ),
148                ( $data['Unhide'] == '1' )
149            );
150        }
151    }
152
153    private function revOrTitle( $revision, $title ) {
154        if ( $revision ) {
155            return $revision;
156        } elseif ( $title ) {
157            return Title::newFromText( $title )->getLatestRevID();
158        }
159
160        return null;
161    }
162
163    /**
164     * @internal Callback for HTMLForm
165     * @param string|null $value
166     * @param array $alldata
167     * @return string|bool
168     */
169    public function checkExistingRevision( $value, $alldata ) {
170        if ( $value === '' || $value === null ) {
171            return true;
172        }
173        $revisionRecord = $this->revisionLookup->getRevisionById( (int)$value );
174        if ( $revisionRecord === null ) {
175            return $this->msg( 'compare-revision-not-exists' )->parseAsBlock();
176        }
177
178        return true;
179    }
180
181    protected function getGroupName() {
182        return 'pagetools';
183    }
184}
185
186/** @deprecated class alias since 1.41 */
187class_alias( SpecialComparePages::class, 'SpecialComparePages' );