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