Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 63
0.00% covered (danger)
0.00%
0 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiMergeHistory
0.00% covered (danger)
0.00%
0 / 63
0.00% covered (danger)
0.00%
0 / 9
420
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 33
0.00% covered (danger)
0.00%
0 / 1
156
 merge
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 mustBePosted
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isWriteMode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getAllowedParams
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
2
 needsToken
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getExamplesMessages
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 getHelpUrls
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Copyright © 2015 Geoffrey Mon <geofbot@gmail.com>
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
23use MediaWiki\Page\MergeHistoryFactory;
24use MediaWiki\Page\PageIdentity;
25use MediaWiki\Status\Status;
26use MediaWiki\Title\Title;
27use Wikimedia\ParamValidator\ParamValidator;
28
29/**
30 * API Module to merge page histories
31 * @ingroup API
32 */
33class ApiMergeHistory extends ApiBase {
34
35    private MergeHistoryFactory $mergeHistoryFactory;
36
37    /**
38     * @param ApiMain $mainModule
39     * @param string $moduleName
40     * @param MergeHistoryFactory $mergeHistoryFactory
41     */
42    public function __construct(
43        ApiMain $mainModule,
44        $moduleName,
45        MergeHistoryFactory $mergeHistoryFactory
46    ) {
47        parent::__construct( $mainModule, $moduleName );
48        $this->mergeHistoryFactory = $mergeHistoryFactory;
49    }
50
51    public function execute() {
52        $this->useTransactionalTimeLimit();
53
54        $params = $this->extractRequestParams();
55
56        $this->requireOnlyOneParameter( $params, 'from', 'fromid' );
57        $this->requireOnlyOneParameter( $params, 'to', 'toid' );
58
59        // Get page objects (nonexistent pages get caught in MergeHistory::isValidMerge())
60        if ( isset( $params['from'] ) ) {
61            $fromTitle = Title::newFromText( $params['from'] );
62            if ( !$fromTitle || $fromTitle->isExternal() ) {
63                $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['from'] ) ] );
64            }
65        } elseif ( isset( $params['fromid'] ) ) {
66            $fromTitle = Title::newFromID( $params['fromid'] );
67            if ( !$fromTitle ) {
68                $this->dieWithError( [ 'apierror-nosuchpageid', $params['fromid'] ] );
69            }
70        }
71
72        if ( isset( $params['to'] ) ) {
73            $toTitle = Title::newFromText( $params['to'] );
74            if ( !$toTitle || $toTitle->isExternal() ) {
75                $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['to'] ) ] );
76            }
77        } elseif ( isset( $params['toid'] ) ) {
78            $toTitle = Title::newFromID( $params['toid'] );
79            if ( !$toTitle ) {
80                $this->dieWithError( [ 'apierror-nosuchpageid', $params['toid'] ] );
81            }
82        }
83
84        $reason = $params['reason'];
85        $timestamp = $params['timestamp'];
86
87        // Merge!
88        // @phan-suppress-next-line PhanTypeMismatchArgumentNullable,PhanPossiblyUndeclaredVariable T240141
89        $status = $this->merge( $fromTitle, $toTitle, $timestamp, $reason );
90        if ( !$status->isOK() ) {
91            $this->dieStatus( $status );
92        }
93
94        $r = [
95            // @phan-suppress-next-line PhanPossiblyUndeclaredVariable T240141
96            'from' => $fromTitle->getPrefixedText(),
97            // @phan-suppress-next-line PhanPossiblyUndeclaredVariable T240141
98            'to' => $toTitle->getPrefixedText(),
99            'timestamp' => wfTimestamp( TS_ISO_8601, $params['timestamp'] ),
100            'reason' => $params['reason']
101        ];
102        $result = $this->getResult();
103
104        $result->addValue( null, $this->getModuleName(), $r );
105    }
106
107    /**
108     * @param PageIdentity $from
109     * @param PageIdentity $to
110     * @param string $timestamp
111     * @param string $reason
112     * @return Status
113     */
114    protected function merge( PageIdentity $from, PageIdentity $to, $timestamp, $reason ) {
115        $mh = $this->mergeHistoryFactory->newMergeHistory( $from, $to, $timestamp );
116
117        return $mh->merge( $this->getAuthority(), $reason );
118    }
119
120    public function mustBePosted() {
121        return true;
122    }
123
124    public function isWriteMode() {
125        return true;
126    }
127
128    public function getAllowedParams() {
129        return [
130            'from' => null,
131            'fromid' => [
132                ParamValidator::PARAM_TYPE => 'integer'
133            ],
134            'to' => null,
135            'toid' => [
136                ParamValidator::PARAM_TYPE => 'integer'
137            ],
138            'timestamp' => [
139                ParamValidator::PARAM_TYPE => 'timestamp'
140            ],
141            'reason' => '',
142        ];
143    }
144
145    public function needsToken() {
146        return 'csrf';
147    }
148
149    protected function getExamplesMessages() {
150        return [
151            'action=mergehistory&from=Oldpage&to=Newpage&token=123ABC&' .
152            'reason=Reason'
153            => 'apihelp-mergehistory-example-merge',
154            'action=mergehistory&from=Oldpage&to=Newpage&token=123ABC&' .
155            'reason=Reason&timestamp=2015-12-31T04%3A37%3A41Z' // TODO
156            => 'apihelp-mergehistory-example-merge-timestamp',
157        ];
158    }
159
160    public function getHelpUrls() {
161        return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Mergehistory';
162    }
163}