Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 98
0.00% covered (danger)
0.00%
0 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiImport
0.00% covered (danger)
0.00%
0 / 98
0.00% covered (danger)
0.00%
0 / 9
650
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 / 54
0.00% covered (danger)
0.00%
0 / 1
210
 getAllowedImportSources
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
20
 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 / 24
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 / 5
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 © 2009 Roan Kattouw <roan.kattouw@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\MainConfigNames;
24use Wikimedia\ParamValidator\ParamValidator;
25
26/**
27 * API module that imports an XML file like Special:Import does
28 *
29 * @ingroup API
30 */
31class ApiImport extends ApiBase {
32
33    private WikiImporterFactory $wikiImporterFactory;
34
35    /**
36     * @param ApiMain $main
37     * @param string $action
38     * @param WikiImporterFactory $wikiImporterFactory
39     */
40    public function __construct(
41        ApiMain $main,
42        $action,
43        WikiImporterFactory $wikiImporterFactory
44    ) {
45        parent::__construct( $main, $action );
46
47        $this->wikiImporterFactory = $wikiImporterFactory;
48    }
49
50    public function execute() {
51        $this->useTransactionalTimeLimit();
52        $params = $this->extractRequestParams();
53
54        $this->requireMaxOneParameter( $params, 'namespace', 'rootpage' );
55
56        $isUpload = false;
57        if ( isset( $params['interwikisource'] ) ) {
58            if ( !$this->getAuthority()->isAllowed( 'import' ) ) {
59                $this->dieWithError( 'apierror-cantimport' );
60            }
61            if ( !isset( $params['interwikipage'] ) ) {
62                $this->dieWithError( [ 'apierror-missingparam', 'interwikipage' ] );
63            }
64            $source = ImportStreamSource::newFromInterwiki(
65                $params['interwikisource'],
66                $params['interwikipage'],
67                $params['fullhistory'],
68                $params['templates']
69            );
70            $usernamePrefix = $params['interwikisource'];
71        } else {
72            $isUpload = true;
73            if ( !$this->getAuthority()->isAllowed( 'importupload' ) ) {
74                $this->dieWithError( 'apierror-cantimport-upload' );
75            }
76            $source = ImportStreamSource::newFromUpload( 'xml' );
77            $usernamePrefix = (string)$params['interwikiprefix'];
78            if ( $usernamePrefix === '' ) {
79                $encParamName = $this->encodeParamName( 'interwikiprefix' );
80                $this->dieWithError( [ 'apierror-missingparam', $encParamName ] );
81            }
82        }
83        if ( !$source->isOK() ) {
84            $this->dieStatus( $source );
85        }
86
87        // Check if user can add the log entry tags which were requested
88        if ( $params['tags'] ) {
89            $ableToTag = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $this->getAuthority() );
90            if ( !$ableToTag->isOK() ) {
91                $this->dieStatus( $ableToTag );
92            }
93        }
94
95        $importer = $this->wikiImporterFactory->getWikiImporter( $source->value, $this->getAuthority() );
96        if ( isset( $params['namespace'] ) ) {
97            $importer->setTargetNamespace( $params['namespace'] );
98        } elseif ( isset( $params['rootpage'] ) ) {
99            $statusRootPage = $importer->setTargetRootPage( $params['rootpage'] );
100            if ( !$statusRootPage->isGood() ) {
101                $this->dieStatus( $statusRootPage );
102            }
103        }
104        $importer->setUsernamePrefix( $usernamePrefix, $params['assignknownusers'] );
105        $reporter = new ApiImportReporter(
106            $importer,
107            $isUpload,
108            $params['interwikisource'],
109            $params['summary'],
110            $this
111        );
112        if ( $params['tags'] ) {
113            $reporter->setChangeTags( $params['tags'] );
114        }
115
116        try {
117            $importer->doImport();
118        } catch ( Exception $e ) {
119            $this->dieWithException( $e, [ 'wrap' => 'apierror-import-unknownerror' ] );
120        }
121
122        $resultData = $reporter->getData();
123        $result = $this->getResult();
124        ApiResult::setIndexedTagName( $resultData, 'page' );
125        $result->addValue( null, $this->getModuleName(), $resultData );
126    }
127
128    /**
129     * Returns a list of interwiki prefixes corresponding to each defined import
130     * source.
131     *
132     * @return array
133     * @since 1.27
134     */
135    public function getAllowedImportSources() {
136        $importSources = $this->getConfig()->get( MainConfigNames::ImportSources );
137        $this->getHookRunner()->onImportSources( $importSources );
138
139        $result = [];
140        foreach ( $importSources as $key => $value ) {
141            if ( is_int( $key ) ) {
142                $result[] = $value;
143            } else {
144                foreach ( $value as $subproject ) {
145                    $result[] = "$key:$subproject";
146                }
147            }
148        }
149        return $result;
150    }
151
152    public function mustBePosted() {
153        return true;
154    }
155
156    public function isWriteMode() {
157        return true;
158    }
159
160    public function getAllowedParams() {
161        return [
162            'summary' => null,
163            'xml' => [
164                ParamValidator::PARAM_TYPE => 'upload',
165            ],
166            'interwikiprefix' => [
167                ParamValidator::PARAM_TYPE => 'string',
168            ],
169            'interwikisource' => [
170                ParamValidator::PARAM_TYPE => $this->getAllowedImportSources(),
171            ],
172            'interwikipage' => null,
173            'fullhistory' => false,
174            'templates' => false,
175            'namespace' => [
176                ParamValidator::PARAM_TYPE => 'namespace'
177            ],
178            'assignknownusers' => false,
179            'rootpage' => null,
180            'tags' => [
181                ParamValidator::PARAM_TYPE => 'tags',
182                ParamValidator::PARAM_ISMULTI => true,
183            ],
184        ];
185    }
186
187    public function needsToken() {
188        return 'csrf';
189    }
190
191    protected function getExamplesMessages() {
192        return [
193            'action=import&interwikisource=meta&interwikipage=Help:ParserFunctions&' .
194                'namespace=100&fullhistory=&token=123ABC'
195                => 'apihelp-import-example-import',
196        ];
197    }
198
199    public function getHelpUrls() {
200        return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Import';
201    }
202}