29require_once __DIR__ .
'/Maintenance.php';
58 parent::__construct();
59 $gz = in_array(
'compress.zlib', stream_get_wrappers() )
61 :
'(disabled; requires PHP zlib module)';
62 $bz2 = in_array(
'compress.bzip2', stream_get_wrappers() )
64 :
'(disabled; requires PHP bzip2 module)';
68This script reads pages from an XML file as produced from Special:Export or
69dumpBackup.php, and saves them into the current wiki.
71Compressed XML files may be read directly:
74 .7z (
if 7za executable is in PATH)
76Note that
for very large data sets, importDump.php may be slow; there are
77alternate methods which can be much faster
for full site restoration:
81 $this->stderr = fopen(
"php://stderr",
"wt" );
83 'Report position and speed after every n pages processed',
false,
true );
85 'Import only the pages from namespaces belonging to the list of ' .
86 'pipe-separated namespace names or namespace indexes',
false,
true );
87 $this->
addOption(
'rootpage',
'Pages will be imported as subpages of the specified page',
89 $this->
addOption(
'dry-run',
'Parse dump without actually importing pages' );
90 $this->
addOption(
'debug',
'Output extra verbose debug information' );
91 $this->
addOption(
'uploads',
'Process file upload data if included (experimental)' );
94 'Disable link table updates. Is faster but leaves the wiki in an inconsistent state'
96 $this->
addOption(
'image-base-path',
'Import files from a specified path',
false,
true );
97 $this->
addOption(
'skip-to',
'Start from nth page by skipping first n-1 pages',
false,
true );
98 $this->
addOption(
'username-prefix',
'Prefix for interwiki usernames',
false,
true );
100 'Treat all usernames as interwiki. ' .
101 'The default is to assign edits to local users where they exist.',
104 $this->
addArg(
'file',
'Dump file to import [else use stdin]',
false );
109 $this->
fatalError(
"Wiki is in read-only mode; you'll need to disable it for import to work." );
112 $this->reportingInterval = intval( $this->
getOption(
'report', 100 ) );
113 if ( !$this->reportingInterval ) {
114 $this->reportingInterval = 100;
117 $this->dryRun = $this->
hasOption(
'dry-run' );
118 $this->uploads = $this->
hasOption(
'uploads' );
119 if ( $this->
hasOption(
'image-base-path' ) ) {
120 $this->imageBasePath = $this->
getOption(
'image-base-path' );
122 if ( $this->
hasOption(
'namespaces' ) ) {
126 if ( $this->
hasArg( 0 ) ) {
132 $this->
output(
"Done!\n" );
133 $this->
output(
"You might want to run rebuildrecentchanges.php to regenerate RecentChanges,\n" );
134 $this->
output(
"and initSiteStats.php to update page and revision counts\n" );
138 if ( count( $namespaces ) == 0 ) {
139 $this->nsFilter =
false;
143 $this->nsFilter = array_unique( array_map( [ $this,
'getNsIndex' ], $namespaces ) );
147 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
148 $result = $contLang->getNsIndex( $namespace );
149 if ( $result !==
false ) {
152 $ns = intval( $namespace );
153 if ( strval( $ns ) === $namespace && $contLang->getNsText( $ns ) !==
false ) {
156 $this->
fatalError(
"Unknown namespace text / index specified: $namespace" );
166 if ( $obj instanceof
Title ) {
168 } elseif ( $obj instanceof
Revision ) {
169 $title = $obj->getTitle();
173 throw new MWException(
"Cannot get namespace of object in " . __METHOD__ );
176 if ( is_null(
$title ) ) {
181 $ns =
$title->getNamespace();
183 return is_array( $this->nsFilter ) && !in_array( $ns, $this->nsFilter );
194 $title = $rev->getTitle();
196 $this->
progress(
"Got bogus revision with null title!" );
208 if ( !$this->dryRun ) {
209 call_user_func( $this->importCallback, $rev );
218 if ( $this->uploads ) {
222 $this->uploadCount++;
225 $this->
progress(
"upload: " . $revision->getFilename() );
227 if ( !$this->dryRun ) {
232 return $dbw->deadlockLoop( [ $revision,
'importUpload' ] );
246 if ( !$this->dryRun ) {
247 call_user_func( $this->logItemCallback, $rev );
252 if ( $final xor ( $this->pageCount % $this->reportingInterval == 0 ) ) {
258 if ( !$this->mQuiet ) {
261 $rate = sprintf(
"%.2f", $this->pageCount / $delta );
262 $revrate = sprintf(
"%.2f", $this->revCount / $delta );
267 # Logs dumps don't have page tallies
268 if ( $this->pageCount ) {
269 $this->
progress(
"$this->pageCount ($rate pages/sec $revrate revs/sec)" );
271 $this->
progress(
"$this->revCount ($revrate revs/sec)" );
278 fwrite( $this->stderr, $string .
"\n" );
282 if ( preg_match(
'/\.gz$/', $filename ) ) {
283 $filename =
'compress.zlib://' . $filename;
284 } elseif ( preg_match(
'/\.bz2$/', $filename ) ) {
285 $filename =
'compress.bzip2://' . $filename;
286 } elseif ( preg_match(
'/\.7z$/', $filename ) ) {
287 $filename =
'mediawiki.compress.7z://' . $filename;
290 $file = fopen( $filename,
'rt' );
296 $file = fopen(
'php://stdin',
'rt' );
297 if ( self::posix_isatty(
$file ) ) {
305 $this->startTime = microtime(
true );
311 $importer->disableStatisticsUpdate();
314 $importer->setDebug(
true );
316 if ( $this->
hasOption(
'no-updates' ) ) {
317 $importer->setNoUpdates(
true );
319 if ( $this->
hasOption(
'username-prefix' ) ) {
320 $importer->setUsernamePrefix(
326 $statusRootPage = $importer->setTargetRootPage( $this->
getOption(
'rootpage' ) );
327 if ( !$statusRootPage->isGood() ) {
329 $this->
fatalError( $statusRootPage->getMessage(
false,
false,
'en' )->text() );
334 $nthPage = (int)$this->
getOption(
'skip-to' );
335 $importer->setPageOffset( $nthPage );
336 $this->pageCount = $nthPage - 1;
338 $importer->setPageCallback( [ $this,
'reportPage' ] );
339 $importer->setNoticeCallback(
function ( $msg, $params ) {
340 echo
wfMessage( $msg, $params )->text() .
"\n";
342 $this->importCallback = $importer->setRevisionCallback(
343 [ $this,
'handleRevision' ] );
344 $this->uploadCallback = $importer->setUploadCallback(
345 [ $this,
'handleUpload' ] );
346 $this->logItemCallback = $importer->setLogItemCallback(
347 [ $this,
'handleLogItem' ] );
348 if ( $this->uploads ) {
349 $importer->setImportUploads(
true );
351 if ( $this->imageBasePath ) {
352 $importer->setImageBasePath( $this->imageBasePath );
355 if ( $this->dryRun ) {
356 $importer->setPageOutCallback(
null );
359 return $importer->doImport();
wfWaitForSlaves( $ifWritesSince=null, $wiki=false, $cluster=false, $timeout=null)
Waits for the replica DBs to catch up to the master position.
wfReadOnly()
Check whether the wiki is in read-only mode.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
const RUN_MAINTENANCE_IF_MAIN
Maintenance script that imports XML dump files into the current wiki.
importFromFile( $filename)
callable null $logItemCallback
callable null $uploadCallback
execute()
Do the actual work.
__construct()
Default constructor.
importFromHandle( $handle)
setNsfilter(array $namespaces)
callable null $importCallback
Imports a XML dump from a file (either from file upload, files on disk, or HTTP)
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
addArg( $arg, $description, $required=true)
Add some args that are needed.
output( $out, $channel=null)
Throw some output to the user.
hasArg( $argId=0)
Does a given argument exist?
hasOption( $name)
Checks to see if a particular option exists.
getArg( $argId=0, $default=null)
Get an argument.
addDescription( $text)
Set the description text.
maybeHelp( $force=false)
Maybe show the help.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
getOption( $name, $default=null)
Get an option, or return the default.
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
Represents a title within MediaWiki.
XML file reader for the page data importer.
Represents a revision, log entry or upload during the import process.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.