68 if ( !class_exists(
'XMLReader' ) ) {
69 throw new Exception(
'Import requires PHP to have been compiled with libxml support' );
72 $this->config = $config;
73 $this->hookRunner = Hooks::runner();
75 if ( !in_array(
'uploadsource', stream_get_wrappers() ) ) {
76 stream_wrapper_register(
'uploadsource', UploadSourceAdapter::class );
83 $oldDisable = @libxml_disable_entity_loader(
false );
84 if ( PHP_VERSION_ID >= 80000 ) {
87 "uploadsource://$id",
null, LIBXML_PARSEHUGE );
88 if (
$reader instanceof XMLReader ) {
96 $this->reader =
new XMLReader;
97 $status = $this->reader->open(
98 "uploadsource://$id",
null, LIBXML_PARSEHUGE );
101 $error = libxml_get_last_error();
103 @libxml_disable_entity_loader( $oldDisable );
104 throw new MWException(
'Encountered an internal error while initializing WikiImporter object: ' .
108 @libxml_disable_entity_loader( $oldDisable );
125 return $this->reader;
129 $this->
debug(
"FAILURE: $err" );
130 wfDebug(
"WikiImporter XML error: $err" );
134 if ( $this->mDebug ) {
139 public function warn( $data ) {
143 public function notice( $msg, ...$params ) {
144 if ( is_callable( $this->mNoticeCallback ) ) {
145 call_user_func( $this->mNoticeCallback, $msg, $params );
166 $this->mNoUpdates = $noupdates;
176 $this->pageOffset = $nthPage;
186 return wfSetVar( $this->mNoticeCallback, $callback );
195 $previous = $this->mPageCallback;
196 $this->mPageCallback = $callback;
210 $previous = $this->mPageOutCallback;
211 $this->mPageOutCallback = $callback;
221 $previous = $this->mRevisionCallback;
222 $this->mRevisionCallback = $callback;
232 $previous = $this->mUploadCallback;
233 $this->mUploadCallback = $callback;
243 $previous = $this->mLogItemCallback;
244 $this->mLogItemCallback = $callback;
254 $previous = $this->mSiteInfoCallback;
255 $this->mSiteInfoCallback = $callback;
265 $this->importTitleFactory = $factory;
274 if ( $namespace ===
null ) {
280 MediaWikiServices::getInstance()->getNamespaceInfo()->exists( intval( $namespace ) )
282 $namespace = intval( $namespace );
296 $status = Status::newGood();
297 if ( $rootpage ===
null ) {
300 } elseif ( $rootpage !==
'' ) {
301 $rootpage = rtrim( $rootpage,
'/' );
302 $title = Title::newFromText( $rootpage );
305 $status->fatal(
'import-rootpage-invalid' );
307 !MediaWikiServices::getInstance()->getNamespaceInfo()->
308 hasSubpages(
$title->getNamespace() )
312 : MediaWikiServices::getInstance()->getContentLanguage()->
313 getNsText(
$title->getNamespace() );
314 $status->fatal(
'import-rootpage-nosubpage', $displayNSText );
328 $this->mImageBasePath = $dir;
335 $this->mImportUploads = $import;
344 $this->externalUserNames =
new ExternalUserNames( $usernamePrefix, $assignKnownUsers );
362 $title = $titleAndForeignTitle[0];
363 $page = WikiPage::factory(
$title );
364 $this->countableCache[
'title_' .
$title->getPrefixedText()] = $page->isCountable();
374 if ( !$revision->getContentHandler()->canBeUsedOn( $revision->getTitle() ) ) {
375 $this->
notice(
'import-error-bad-location',
376 $revision->getTitle()->getPrefixedText(),
378 $revision->getModel(),
379 $revision->getFormat() );
385 return $revision->importOldRevision();
387 $this->
notice(
'import-error-unserialize',
388 $revision->getTitle()->getPrefixedText(),
390 $revision->getModel(),
391 $revision->getFormat() );
403 return $revision->importLogItem();
412 return $revision->importUpload();
425 $sRevCount, $pageInfo
434 $page = WikiPage::factory(
$title );
435 $page->loadPageData(
'fromdbmaster' );
438 wfDebug( __METHOD__ .
': Skipping article count adjustment for ' .
$title .
439 ' because WikiPage::getContent() returned null' );
441 $editInfo = $page->prepareContentForEdit(
$content );
442 $countKey =
'title_' .
$title->getPrefixedText();
443 $countable = $page->isCountable( $editInfo );
444 if ( array_key_exists( $countKey, $this->countableCache ) &&
445 $countable != $this->countableCache[$countKey] ) {
446 DeferredUpdates::addUpdate( SiteStatsUpdate::factory( [
447 'articles' => ( (
int)$countable - (
int)$this->countableCache[$countKey] )
453 return $this->hookRunner->onAfterImportPage(
$title, $foreignTitle,
454 $revCount, $sRevCount, $pageInfo );
462 $this->
debug(
"Got revision:" );
463 if ( is_object( $revision->title ) ) {
464 $this->
debug(
"-- Title: " . $revision->title->getPrefixedText() );
466 $this->
debug(
"-- Title: <invalid>" );
468 $this->
debug(
"-- User: " . $revision->user_text );
469 $this->
debug(
"-- Timestamp: " . $revision->timestamp );
470 $this->
debug(
"-- Comment: " . $revision->comment );
471 $this->
debug(
"-- Text: " . $revision->text );
480 if ( isset( $this->mSiteInfoCallback ) ) {
481 return call_user_func_array( $this->mSiteInfoCallback,
482 [ $siteInfo, $this ] );
493 if ( isset( $this->mPageCallback ) ) {
494 call_user_func( $this->mPageCallback,
$title );
507 $sucCount, $pageInfo ) {
508 if ( isset( $this->mPageOutCallback ) ) {
509 call_user_func_array( $this->mPageOutCallback, func_get_args() );
519 if ( isset( $this->mRevisionCallback ) ) {
520 return call_user_func_array( $this->mRevisionCallback,
521 [ $revision, $this ] );
533 if ( isset( $this->mLogItemCallback ) ) {
534 return call_user_func_array( $this->mLogItemCallback,
535 [ $revision, $this ] );
548 return $this->reader->getAttribute( $attr );
559 if ( $this->reader->isEmptyElement ) {
563 while ( $this->reader->read() ) {
564 switch ( $this->reader->nodeType ) {
565 case XMLReader::TEXT:
566 case XMLReader::CDATA:
567 case XMLReader::SIGNIFICANT_WHITESPACE:
568 $buffer .= $this->reader->value;
570 case XMLReader::END_ELEMENT:
575 $this->reader->close();
590 $oldDisable = @libxml_disable_entity_loader(
true );
593 $this->reader->read();
595 if ( $this->reader->localName !=
'mediawiki' ) {
597 @libxml_disable_entity_loader( $oldDisable );
599 "Expected '<mediawiki>' tag, got '<{$this->reader->localName}>' tag."
602 $this->
debug(
"<mediawiki> tag is correct." );
604 $this->
debug(
"Starting primary dump processing loop." );
606 $keepReading = $this->reader->read();
609 while ( $keepReading ) {
610 $tag = $this->reader->localName;
611 if ( $this->pageOffset ) {
612 if ( $tag ===
'page' ) {
615 if ( $pageCount < $this->pageOffset ) {
616 $keepReading = $this->reader->next();
620 $type = $this->reader->nodeType;
622 if ( !$this->hookRunner->onImportHandleToplevelXMLTag( $this ) ) {
624 } elseif ( $tag ==
'mediawiki' &&
$type == XMLReader::END_ELEMENT ) {
626 } elseif ( $tag ==
'siteinfo' ) {
628 } elseif ( $tag ==
'page' ) {
630 } elseif ( $tag ==
'logitem' ) {
632 } elseif ( $tag !=
'#text' ) {
633 $this->
warn(
"Unhandled top-level XML tag $tag" );
639 $keepReading = $this->reader->next();
641 $this->
debug(
"Skip" );
643 $keepReading = $this->reader->read();
648 @libxml_disable_entity_loader( $oldDisable );
649 $this->reader->close();
656 $this->
debug(
"Enter site info handler." );
660 $normalFields = [
'sitename',
'base',
'generator',
'case' ];
662 while ( $this->reader->read() ) {
663 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
664 $this->reader->localName ==
'siteinfo' ) {
668 $tag = $this->reader->localName;
670 if ( $tag ==
'namespace' ) {
673 } elseif ( in_array( $tag, $normalFields ) ) {
678 $siteInfo[
'_namespaces'] = $this->foreignNamespaces;
683 $this->
debug(
"Enter log item handler." );
687 $normalFields = [
'id',
'comment',
'type',
'action',
'timestamp',
688 'logtitle',
'params' ];
690 while ( $this->reader->read() ) {
691 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
692 $this->reader->localName ==
'logitem' ) {
696 $tag = $this->reader->localName;
698 if ( !$this->hookRunner->onImportHandleLogItemXMLTag( $this, $logInfo ) ) {
700 } elseif ( in_array( $tag, $normalFields ) ) {
702 } elseif ( $tag ==
'contributor' ) {
704 } elseif ( $tag !=
'#text' ) {
705 $this->
warn(
"Unhandled log-item XML tag $tag" );
719 if ( isset( $logInfo[
'id'] ) ) {
720 $revision->setID( $logInfo[
'id'] );
722 $revision->setType( $logInfo[
'type'] );
723 $revision->setAction( $logInfo[
'action'] );
724 if ( isset( $logInfo[
'timestamp'] ) ) {
725 $revision->setTimestamp( $logInfo[
'timestamp'] );
727 if ( isset( $logInfo[
'params'] ) ) {
728 $revision->setParams( $logInfo[
'params'] );
730 if ( isset( $logInfo[
'logtitle'] ) ) {
733 $revision->setTitle( Title::newFromText( $logInfo[
'logtitle'] ) );
736 $revision->setNoUpdates( $this->mNoUpdates );
738 if ( isset( $logInfo[
'comment'] ) ) {
739 $revision->setComment( $logInfo[
'comment'] );
742 if ( isset( $logInfo[
'contributor'][
'ip'] ) ) {
743 $revision->setUserIP( $logInfo[
'contributor'][
'ip'] );
746 if ( !isset( $logInfo[
'contributor'][
'username'] ) ) {
747 $revision->setUsername( $this->externalUserNames->addPrefix(
'Unknown user' ) );
749 $revision->setUsername(
750 $this->externalUserNames->applyPrefix( $logInfo[
'contributor'][
'username'] )
759 $this->
debug(
"Enter page handler." );
760 $pageInfo = [
'revisionCount' => 0,
'successfulRevisionCount' => 0 ];
763 $normalFields = [
'title',
'ns',
'id',
'redirect',
'restrictions' ];
768 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
769 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
770 $this->reader->localName ==
'page' ) {
776 $tag = $this->reader->localName;
781 } elseif ( !$this->hookRunner->onImportHandlePageXMLTag( $this, $pageInfo ) ) {
783 } elseif ( in_array( $tag, $normalFields ) ) {
791 if ( $tag ==
'redirect' ) {
796 } elseif ( $tag ==
'revision' || $tag ==
'upload' ) {
799 $pageInfo[
'ns'] ??
null );
802 if ( is_array(
$title ) ) {
804 list( $pageInfo[
'_title'], $foreignTitle ) =
$title;
812 if ( $tag ==
'revision' ) {
818 } elseif ( $tag !=
'#text' ) {
819 $this->
warn(
"Unhandled page XML tag $tag" );
829 if ( array_key_exists(
'_title', $pageInfo ) ) {
831 $pageInfo[
'revisionCount'],
832 $pageInfo[
'successfulRevisionCount'],
841 $this->
debug(
"Enter revision handler" );
844 $normalFields = [
'id',
'parentid',
'timestamp',
'comment',
'minor',
'origin',
845 'model',
'format',
'text',
'sha1' ];
849 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
850 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
851 $this->reader->localName ==
'revision' ) {
855 $tag = $this->reader->localName;
857 if ( !$this->hookRunner->onImportHandleRevisionXMLTag(
858 $this, $pageInfo, $revisionInfo )
861 } elseif ( in_array( $tag, $normalFields ) ) {
863 } elseif ( $tag ==
'content' ) {
866 } elseif ( $tag ==
'contributor' ) {
868 } elseif ( $tag !=
'#text' ) {
869 $this->
warn(
"Unhandled revision XML tag $tag" );
874 $pageInfo[
'revisionCount']++;
876 $pageInfo[
'successfulRevisionCount']++;
881 $this->
debug(
"Enter content handler" );
884 $normalFields = [
'role',
'origin',
'model',
'format',
'text' ];
888 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
889 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
890 $this->reader->localName ==
'content' ) {
894 $tag = $this->reader->localName;
896 if ( !$this->hookRunner->onImportHandleContentXMLTag(
897 $this, $contentInfo )
900 } elseif ( in_array( $tag, $normalFields ) ) {
902 } elseif ( $tag !=
'#text' ) {
903 $this->
warn(
"Unhandled content XML tag $tag" );
922 if ( !isset( $contentInfo[
'text'] ) ) {
923 throw new MWException(
'Missing text field in import.' );
930 if ( ( !isset( $contentInfo[
'model'] ) ||
931 in_array( $contentInfo[
'model'], [
943 "the revision with ID $revisionId" :
945 ) .
" exceeds the maximum allowable size ($wgMaxArticleSize KB)" );
948 $role = $contentInfo[
'role'] ?? SlotRecord::MAIN;
952 $text = $handler->importTransform( $contentInfo[
'text'] );
954 $content = $handler->unserializeContent( $text );
968 $revId = $revisionInfo[
'id'] ?? 0;
970 $revision->setID( $revisionInfo[
'id'] );
973 $title = $pageInfo[
'_title'];
974 $revision->setTitle(
$title );
977 $revision->setContent( SlotRecord::MAIN,
$content );
979 foreach ( $revisionInfo[
'content'] ?? [] as $slotInfo ) {
980 if ( !isset( $slotInfo[
'role'] ) ) {
981 throw new MWException(
"Missing role for imported slot." );
985 $revision->setContent( $slotInfo[
'role'],
$content );
987 $revision->setTimestamp( $revisionInfo[
'timestamp'] ??
wfTimestampNow() );
989 if ( isset( $revisionInfo[
'comment'] ) ) {
990 $revision->setComment( $revisionInfo[
'comment'] );
993 if ( isset( $revisionInfo[
'minor'] ) ) {
994 $revision->setMinor(
true );
996 if ( isset( $revisionInfo[
'contributor'][
'ip'] ) ) {
997 $revision->setUserIP( $revisionInfo[
'contributor'][
'ip'] );
998 } elseif ( isset( $revisionInfo[
'contributor'][
'username'] ) ) {
999 $revision->setUsername(
1000 $this->externalUserNames->applyPrefix( $revisionInfo[
'contributor'][
'username'] )
1003 $revision->setUsername( $this->externalUserNames->addPrefix(
'Unknown user' ) );
1005 if ( isset( $revisionInfo[
'sha1'] ) ) {
1006 $revision->setSha1Base36( $revisionInfo[
'sha1'] );
1008 $revision->setNoUpdates( $this->mNoUpdates );
1018 $this->
debug(
"Enter upload handler" );
1021 $normalFields = [
'timestamp',
'comment',
'filename',
'text',
1022 'src',
'size',
'sha1base36',
'archivename',
'rel' ];
1026 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
1027 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
1028 $this->reader->localName ==
'upload' ) {
1032 $tag = $this->reader->localName;
1034 if ( !$this->hookRunner->onImportHandleUploadXMLTag( $this, $pageInfo ) ) {
1036 } elseif ( in_array( $tag, $normalFields ) ) {
1038 } elseif ( $tag ==
'contributor' ) {
1040 } elseif ( $tag ==
'contents' ) {
1042 $encoding = $this->reader->getAttribute(
'encoding' );
1043 if ( $encoding ===
'base64' ) {
1044 $uploadInfo[
'fileSrc'] = $this->
dumpTemp( base64_decode( $contents ) );
1045 $uploadInfo[
'isTempSrc'] =
true;
1047 } elseif ( $tag !=
'#text' ) {
1048 $this->
warn(
"Unhandled upload XML tag $tag" );
1053 if ( $this->mImageBasePath && isset( $uploadInfo[
'rel'] ) ) {
1054 $path =
"{$this->mImageBasePath}/{$uploadInfo['rel']}";
1055 if ( file_exists(
$path ) ) {
1056 $uploadInfo[
'fileSrc'] =
$path;
1057 $uploadInfo[
'isTempSrc'] =
false;
1061 if ( $this->mImportUploads ) {
1071 $filename = tempnam(
wfTempDir(),
'importupload' );
1072 file_put_contents( $filename, $contents );
1083 $revId = $pageInfo[
'id'];
1084 $title = $pageInfo[
'_title'];
1086 $uploadInfo[
'text'] = $uploadInfo[
'text'] ??
'';
1089 $revision->setTitle(
$title );
1090 $revision->setID( $revId );
1091 $revision->setTimestamp( $uploadInfo[
'timestamp'] );
1092 $revision->setContent( SlotRecord::MAIN,
$content );
1093 $revision->setFilename( $uploadInfo[
'filename'] );
1094 if ( isset( $uploadInfo[
'archivename'] ) ) {
1095 $revision->setArchiveName( $uploadInfo[
'archivename'] );
1097 $revision->setSrc( $uploadInfo[
'src'] );
1098 if ( isset( $uploadInfo[
'fileSrc'] ) ) {
1099 $revision->setFileSrc( $uploadInfo[
'fileSrc'],
1100 !empty( $uploadInfo[
'isTempSrc'] ) );
1102 if ( isset( $uploadInfo[
'sha1base36'] ) ) {
1103 $revision->setSha1Base36( $uploadInfo[
'sha1base36'] );
1105 $revision->setSize( intval( $uploadInfo[
'size'] ) );
1106 $revision->setComment( $uploadInfo[
'comment'] );
1108 if ( isset( $uploadInfo[
'contributor'][
'ip'] ) ) {
1109 $revision->setUserIP( $uploadInfo[
'contributor'][
'ip'] );
1111 if ( isset( $uploadInfo[
'contributor'][
'username'] ) ) {
1112 $revision->setUsername(
1113 $this->externalUserNames->applyPrefix( $uploadInfo[
'contributor'][
'username'] )
1116 $revision->setNoUpdates( $this->mNoUpdates );
1118 return call_user_func( $this->mUploadCallback, $revision );
1125 $this->
debug(
"Enter contributor handler." );
1126 $fields = [
'id',
'ip',
'username' ];
1129 if ( $this->reader->isEmptyElement ) {
1132 while ( $this->reader->read() ) {
1133 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
1134 $this->reader->localName ==
'contributor' ) {
1138 $tag = $this->reader->localName;
1140 if ( in_array( $tag, $fields ) ) {
1154 if ( $this->foreignNamespaces ===
null ) {
1158 $this->foreignNamespaces );
1161 $foreignTitle = $foreignTitleFactory->createForeignTitle( $text,
1164 $title = $this->importTitleFactory->createTitleFromForeignTitle(
1167 $commandLineMode = $this->config->get(
'CommandLineMode' );
1169 # Invalid page title? Ignore the page
1170 $this->
notice(
'import-error-invalid', $foreignTitle->getFullText() );
1172 } elseif (
$title->isExternal() ) {
1173 $this->
notice(
'import-error-interwiki',
$title->getPrefixedText() );
1175 } elseif ( !
$title->canExist() ) {
1176 $this->
notice(
'import-error-special',
$title->getPrefixedText() );
1178 } elseif ( !$commandLineMode ) {
1179 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
1180 $user = RequestContext::getMain()->getUser();
1182 if ( !$permissionManager->userCan(
'edit', $user,
$title ) ) {
1183 # Do not import if the importing wiki user cannot edit this page
1184 $this->
notice(
'import-error-edit',
$title->getPrefixedText() );
1189 if ( !
$title->exists() && !$permissionManager->userCan(
'create', $user,
$title ) ) {
1190 # Do not import if the importing wiki user cannot create this page
1191 $this->
notice(
'import-error-create',
$title->getPrefixedText() );
1197 return [
$title, $foreignTitle ];
1205 return MediaWikiServices::getInstance()
1206 ->getContentHandlerFactory()
1207 ->getContentHandler( $model );
1217 return MediaWikiServices::getInstance()
1218 ->getSlotRoleRegistry()
1219 ->getRoleHandler( $role )
1220 ->getDefaultModel(
$title );
$wgMaxArticleSize
Maximum article size in kilobytes.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfTempDir()
Tries to get the system directory for temporary files.
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
wfSetVar(&$dest, $source, $force=false)
Sets dest to source and returns the original value of dest If source is NULL, it just returns the val...
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Class to parse and build external user names.
Exception representing a failure to serialize or unserialize a content object.
A parser that translates page titles on a foreign wiki into ForeignTitle objects, with no knowledge o...
A class to convert page titles on a foreign wiki (ForeignTitle objects) into page titles on the local...
A parser that translates page titles on a foreign wiki into ForeignTitle objects, using information a...
A class to convert page titles on a foreign wiki (ForeignTitle objects) into page titles on the local...
A class to convert page titles on a foreign wiki (ForeignTitle objects) into page titles on the local...
Represents a title within MediaWiki.
static registerSource(ImportSource $source)
XML file reader for the page data importer.
finishImportPage( $title, $foreignTitle, $revCount, $sRevCount, $pageInfo)
Mostly for hook use.
setImportUploads( $import)
doImport()
Primary entry point.
setPageCallback( $callback)
Sets the action to perform as each new page in the stream is reached.
setUsernamePrefix( $usernamePrefix, $assignKnownUsers)
ExternalUserNames $externalUserNames
setNoUpdates( $noupdates)
Set 'no updates' mode.
pageOutCallback( $title, $foreignTitle, $revCount, $sucCount, $pageInfo)
Notify the callback function when a "</page>" is closed.
setLogItemCallback( $callback)
Sets the action to perform as each log item reached.
importUpload( $revision)
Dummy for now...
setImportTitleFactory( $factory)
Sets the factory object to use to convert ForeignTitle objects into local Title objects.
setSiteInfoCallback( $callback)
Sets the action to perform when site info is encountered.
getContentHandler( $model)
nodeAttribute( $attr)
Retrieves the contents of the named attribute of the current element.
pageCallback( $title)
Notify the callback function when a new "<page>" is reached.
processLogItem( $logInfo)
setTargetNamespace( $namespace)
Set a target namespace to override the defaults.
setPageOffset( $nthPage)
Sets 'pageOffset' value.
debugRevisionHandler(&$revision)
Alternate per-revision callback, for debugging.
nodeContents()
Shouldn't something like this be built-in to XMLReader? Fetches text contents of the current element,...
importLogItem( $revision)
Default per-revision callback, performs the import.
getDefaultContentModel( $title, $role)
handleRevision(&$pageInfo)
revisionCallback( $revision)
Notify the callback function of a revision.
logItemCallback( $revision)
Notify the callback function of a new log item.
setDebug( $debug)
Set debug mode...
processRevision( $pageInfo, $revisionInfo)
processUpload( $pageInfo, $uploadInfo)
bool $disableStatisticsUpdate
processTitle( $text, $ns=null)
makeContent(Title $title, $revisionId, $contentInfo)
notice( $msg,... $params)
importRevision( $revision)
Default per-revision callback, performs the import.
ImportTitleFactory $importTitleFactory
__construct(ImportSource $source, Config $config)
Creates an ImportXMLReader drawing from the source provided.
setPageOutCallback( $callback)
Sets the action to perform as each page in the stream is completed.
setTargetRootPage( $rootpage)
Set a target root page under which all pages are imported.
setNoticeCallback( $callback)
Set a callback that displays notice messages.
beforeImportPage( $titleAndForeignTitle)
Default per-page callback.
disableStatisticsUpdate()
Statistics update can cause a lot of time.
siteInfoCallback( $siteInfo)
Notify the callback function of site info.
setRevisionCallback( $callback)
Sets the action to perform as each page revision is reached.
setUploadCallback( $callback)
Sets the action to perform as each file upload version is reached.
Represents a revision, log entry or upload during the import process.
Interface for configuration instances.
Source interface for XML import.
Represents an object that can convert page titles on a foreign wiki (ForeignTitle objects) into page ...