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