65 private $sourceAdapterId;
68 private $foreignNamespaces =
null;
71 private $mLogItemCallback;
74 private $mUploadCallback;
77 private $mRevisionCallback;
80 private $mPageCallback;
83 private $mSiteInfoCallback;
86 private $mPageOutCallback;
89 private $mNoticeCallback;
95 private $mImportUploads;
98 private $mImageBasePath;
101 private $mNoUpdates =
false;
104 private $pageOffset = 0;
110 private $importTitleFactory;
116 private $countableCache = [];
119 private $disableStatisticsUpdate =
false;
122 private $externalUserNames;
125 private $contentLanguage;
128 private $namespaceInfo;
131 private $titleFactory;
134 private $wikiPageFactory;
137 private $uploadRevisionImporter;
140 private $permissionManager;
143 private $contentHandlerFactory;
146 private $slotRoleRegistry;
176 $this->config = $config;
177 $this->hookRunner =
new HookRunner( $hookContainer );
178 $this->contentLanguage = $contentLanguage;
179 $this->namespaceInfo = $namespaceInfo;
180 $this->titleFactory = $titleFactory;
181 $this->wikiPageFactory = $wikiPageFactory;
182 $this->uploadRevisionImporter = $uploadRevisionImporter;
183 $this->permissionManager = $permissionManager;
184 $this->contentHandlerFactory = $contentHandlerFactory;
185 $this->slotRoleRegistry = $slotRoleRegistry;
187 if ( !in_array(
'uploadsource', stream_get_wrappers() ) ) {
188 stream_wrapper_register(
'uploadsource', UploadSourceAdapter::class );
202 $this->contentLanguage,
203 $this->namespaceInfo,
213 return $this->reader;
220 $this->
debug(
"FAILURE: $err" );
221 wfDebug(
"WikiImporter XML error: $err" );
228 if ( $this->mDebug ) {
236 public function warn( $data ) {
244 public function notice( $msg, ...$params ) {
245 if ( is_callable( $this->mNoticeCallback ) ) {
246 call_user_func( $this->mNoticeCallback, $msg, $params );
259 $this->mDebug = $debug;
267 $this->mNoUpdates = $noupdates;
277 $this->pageOffset = $nthPage;
287 return wfSetVar( $this->mNoticeCallback, $callback );
296 $previous = $this->mPageCallback;
297 $this->mPageCallback = $callback;
311 $previous = $this->mPageOutCallback;
312 $this->mPageOutCallback = $callback;
322 $previous = $this->mRevisionCallback;
323 $this->mRevisionCallback = $callback;
333 $previous = $this->mUploadCallback;
334 $this->mUploadCallback = $callback;
344 $previous = $this->mLogItemCallback;
345 $this->mLogItemCallback = $callback;
355 $previous = $this->mSiteInfoCallback;
356 $this->mSiteInfoCallback = $callback;
366 $this->importTitleFactory = $factory;
375 if ( $namespace ===
null ) {
379 $this->contentLanguage,
380 $this->namespaceInfo,
387 $this->namespaceInfo->exists( intval( $namespace ) )
389 $namespace = intval( $namespace );
392 $this->namespaceInfo,
409 $status = Status::newGood();
410 $nsInfo = $this->namespaceInfo;
411 if ( $rootpage ===
null ) {
415 $this->contentLanguage,
420 } elseif ( $rootpage !==
'' ) {
421 $rootpage = rtrim( $rootpage,
'/' );
422 $title = Title::newFromText( $rootpage );
425 $status->fatal(
'import-rootpage-invalid' );
426 } elseif ( !$nsInfo->hasSubpages( $title->
getNamespace() ) ) {
429 : $this->contentLanguage->getNsText( $title->
getNamespace() );
430 $status->fatal(
'import-rootpage-nosubpage', $displayNSText );
450 $this->mImageBasePath = $dir;
457 $this->mImportUploads = $import;
466 $this->externalUserNames =
new ExternalUserNames( $usernamePrefix, $assignKnownUsers );
484 $title = $titleAndForeignTitle[0];
485 $page = $this->wikiPageFactory->newFromTitle( $title );
486 $this->countableCache[
'title_' . $title->
getPrefixedText()] = $page->isCountable();
496 if ( !$revision->getContentHandler()->canBeUsedOn( $revision->getTitle() ) ) {
497 $this->
notice(
'import-error-bad-location',
498 $revision->getTitle()->getPrefixedText(),
500 $revision->getModel(),
501 $revision->getFormat()
508 return $revision->importOldRevision();
510 $this->
notice(
'import-error-unserialize',
511 $revision->getTitle()->getPrefixedText(),
513 $revision->getModel(),
514 $revision->getFormat()
527 return $revision->importLogItem();
536 $status = $this->uploadRevisionImporter->import( $revision );
537 return $status->isGood();
550 $sRevCount, $pageInfo
559 $page = $this->wikiPageFactory->newFromTitle( $pageIdentity );
561 $page->loadPageData( WikiPage::READ_LATEST );
562 $rev = $page->getRevisionRecord();
563 if ( $rev ===
null ) {
565 wfDebug( __METHOD__ .
': Skipping article count adjustment for ' . $pageIdentity .
566 ' because WikiPage::getRevisionRecord() returned null' );
568 $user = RequestContext::getMain()->getUser();
569 $update = $page->newPageUpdater( $user )->prepareUpdate();
570 $countKey =
'title_' . CacheKeyHelper::getKeyForPage( $pageIdentity );
571 $countable = $update->isCountable();
572 if ( array_key_exists( $countKey, $this->countableCache ) &&
573 $countable != $this->countableCache[$countKey] ) {
574 DeferredUpdates::addUpdate( SiteStatsUpdate::factory( [
575 'articles' => ( (
int)$countable - (
int)$this->countableCache[$countKey] )
581 $title = Title::newFromPageIdentity( $pageIdentity );
582 return $this->hookRunner->onAfterImportPage( $title, $foreignTitle,
583 $revCount, $sRevCount, $pageInfo );
591 private function siteInfoCallback( $siteInfo ) {
592 if ( isset( $this->mSiteInfoCallback ) ) {
593 return call_user_func_array(
594 $this->mSiteInfoCallback,
607 if ( isset( $this->mPageCallback ) ) {
608 call_user_func( $this->mPageCallback, $title );
620 private function pageOutCallback(
PageIdentity $pageIdentity, $foreignTitle, $revCount,
621 $sucCount, $pageInfo ) {
622 if ( isset( $this->mPageOutCallback ) ) {
623 call_user_func_array( $this->mPageOutCallback, func_get_args() );
632 private function revisionCallback( $revision ) {
633 if ( isset( $this->mRevisionCallback ) ) {
634 return call_user_func_array(
635 $this->mRevisionCallback,
648 private function logItemCallback( $revision ) {
649 if ( isset( $this->mLogItemCallback ) ) {
650 return call_user_func_array(
651 $this->mLogItemCallback,
666 return $this->reader->getAttribute( $attr ) ??
'';
677 if ( $this->reader->isEmptyElement ) {
681 while ( $this->reader->read() ) {
682 switch ( $this->reader->nodeType ) {
683 case XMLReader::TEXT:
684 case XMLReader::CDATA:
685 case XMLReader::SIGNIFICANT_WHITESPACE:
686 $buffer .= $this->reader->value;
688 case XMLReader::END_ELEMENT:
693 $this->reader->close();
703 $this->syntaxCheckXML();
709 $oldDisable = @libxml_disable_entity_loader(
true );
711 $this->reader->read();
713 if ( $this->reader->localName !=
'mediawiki' ) {
715 @libxml_disable_entity_loader( $oldDisable );
716 $error = libxml_get_last_error();
718 throw new NormalizedException(
"XML error at line {line}: {message}", [
719 'line' => $error->line,
720 'message' => $error->message,
724 "Expected '<mediawiki>' tag, got '<{$this->reader->localName}>' tag."
728 $this->
debug(
"<mediawiki> tag is correct." );
730 $this->
debug(
"Starting primary dump processing loop." );
732 $keepReading = $this->reader->read();
735 while ( $keepReading ) {
736 $tag = $this->reader->localName;
737 if ( $this->pageOffset ) {
738 if ( $tag ===
'page' ) {
741 if ( $pageCount < $this->pageOffset ) {
742 $keepReading = $this->reader->next();
746 $type = $this->reader->nodeType;
748 if ( !$this->hookRunner->onImportHandleToplevelXMLTag( $this ) ) {
750 } elseif ( $tag ==
'mediawiki' && $type == XMLReader::END_ELEMENT ) {
752 } elseif ( $tag ==
'siteinfo' ) {
753 $this->handleSiteInfo();
754 } elseif ( $tag ==
'page' ) {
756 } elseif ( $tag ==
'logitem' ) {
757 $this->handleLogItem();
758 } elseif ( $tag !=
'#text' ) {
759 $this->
warn(
"Unhandled top-level XML tag $tag" );
765 $keepReading = $this->reader->next();
767 $this->
debug(
"Skip" );
769 $keepReading = $this->reader->read();
774 @libxml_disable_entity_loader( $oldDisable );
775 $this->reader->close();
781 private function handleSiteInfo() {
782 $this->debug(
"Enter site info handler." );
786 $normalFields = [
'sitename',
'base',
'generator',
'case' ];
788 while ( $this->reader->read() ) {
789 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
790 $this->reader->localName ==
'siteinfo' ) {
794 $tag = $this->reader->localName;
796 if ( $tag ==
'namespace' ) {
799 } elseif ( in_array( $tag, $normalFields ) ) {
804 $siteInfo[
'_namespaces'] = $this->foreignNamespaces;
805 $this->siteInfoCallback( $siteInfo );
808 private function handleLogItem() {
809 $this->
debug(
"Enter log item handler." );
813 $normalFields = [
'id',
'comment',
'type',
'action',
'timestamp',
814 'logtitle',
'params' ];
816 while ( $this->reader->read() ) {
817 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
818 $this->reader->localName ==
'logitem' ) {
822 $tag = $this->reader->localName;
824 if ( !$this->hookRunner->onImportHandleLogItemXMLTag( $this, $logInfo ) ) {
826 } elseif ( in_array( $tag, $normalFields ) ) {
828 } elseif ( $tag ==
'contributor' ) {
829 $logInfo[
'contributor'] = $this->handleContributor();
830 } elseif ( $tag !=
'#text' ) {
831 $this->
warn(
"Unhandled log-item XML tag $tag" );
835 $this->processLogItem( $logInfo );
842 private function processLogItem( $logInfo ) {
845 if ( isset( $logInfo[
'id'] ) ) {
846 $revision->setID( $logInfo[
'id'] );
848 $revision->setType( $logInfo[
'type'] );
849 $revision->setAction( $logInfo[
'action'] );
850 if ( isset( $logInfo[
'timestamp'] ) ) {
851 $revision->setTimestamp( $logInfo[
'timestamp'] );
853 if ( isset( $logInfo[
'params'] ) ) {
854 $revision->setParams( $logInfo[
'params'] );
856 if ( isset( $logInfo[
'logtitle'] ) ) {
859 $revision->setTitle( Title::newFromText( $logInfo[
'logtitle'] ) );
862 $revision->setNoUpdates( $this->mNoUpdates );
864 if ( isset( $logInfo[
'comment'] ) ) {
865 $revision->setComment( $logInfo[
'comment'] );
868 if ( isset( $logInfo[
'contributor'][
'username'] ) ) {
869 $revision->setUsername(
870 $this->externalUserNames->applyPrefix( $logInfo[
'contributor'][
'username'] )
872 } elseif ( isset( $logInfo[
'contributor'][
'ip'] ) ) {
873 $revision->setUserIP( $logInfo[
'contributor'][
'ip'] );
875 $revision->setUsername( $this->externalUserNames->addPrefix(
'Unknown user' ) );
878 return $this->logItemCallback( $revision );
881 private function handlePage() {
883 $this->
debug(
"Enter page handler." );
884 $pageInfo = [
'revisionCount' => 0,
'successfulRevisionCount' => 0 ];
887 $normalFields = [
'title',
'ns',
'id',
'redirect',
'restrictions' ];
892 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
893 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
894 $this->reader->localName ==
'page' ) {
900 $tag = $this->reader->localName;
905 } elseif ( !$this->hookRunner->onImportHandlePageXMLTag( $this, $pageInfo ) ) {
907 } elseif ( in_array( $tag, $normalFields ) ) {
915 if ( $tag ==
'redirect' ) {
920 } elseif ( $tag ==
'revision' || $tag ==
'upload' ) {
921 if ( !isset( $title ) ) {
922 $title = $this->processTitle( $pageInfo[
'title'],
923 $pageInfo[
'ns'] ??
null );
926 if ( is_array( $title ) ) {
928 [ $pageInfo[
'_title'], $foreignTitle ] = $title;
936 if ( $tag ==
'revision' ) {
937 $this->handleRevision( $pageInfo );
939 $this->handleUpload( $pageInfo );
942 } elseif ( $tag !=
'#text' ) {
943 $this->
warn(
"Unhandled page XML tag $tag" );
953 if ( array_key_exists(
'_title', $pageInfo ) ) {
955 $title = $pageInfo[
'_title'];
956 $this->pageOutCallback(
960 $pageInfo[
'revisionCount'],
961 $pageInfo[
'successfulRevisionCount'],
970 private function handleRevision( &$pageInfo ) {
971 $this->
debug(
"Enter revision handler" );
974 $normalFields = [
'id',
'parentid',
'timestamp',
'comment',
'minor',
'origin',
975 'model',
'format',
'text',
'sha1' ];
979 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
980 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
981 $this->reader->localName ==
'revision' ) {
985 $tag = $this->reader->localName;
987 if ( !$this->hookRunner->onImportHandleRevisionXMLTag(
988 $this, $pageInfo, $revisionInfo )
991 } elseif ( in_array( $tag, $normalFields ) ) {
993 } elseif ( $tag ==
'content' ) {
995 $revisionInfo[$tag][] = $this->handleContent();
996 } elseif ( $tag ==
'contributor' ) {
997 $revisionInfo[
'contributor'] = $this->handleContributor();
998 } elseif ( $tag !=
'#text' ) {
999 $this->
warn(
"Unhandled revision XML tag $tag" );
1004 $pageInfo[
'revisionCount']++;
1005 if ( $this->processRevision( $pageInfo, $revisionInfo ) ) {
1006 $pageInfo[
'successfulRevisionCount']++;
1010 private function handleContent() {
1011 $this->
debug(
"Enter content handler" );
1014 $normalFields = [
'role',
'origin',
'model',
'format',
'text' ];
1018 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
1019 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
1020 $this->reader->localName ==
'content' ) {
1024 $tag = $this->reader->localName;
1026 if ( !$this->hookRunner->onImportHandleContentXMLTag(
1027 $this, $contentInfo )
1030 } elseif ( in_array( $tag, $normalFields ) ) {
1032 } elseif ( $tag !=
'#text' ) {
1033 $this->
warn(
"Unhandled content XML tag $tag" );
1038 return $contentInfo;
1049 private function makeContent(
Title $title, $revisionId, $contentInfo ) {
1050 $maxArticleSize = MediaWikiServices::getInstance()->getMainConfig()->get(
1051 MainConfigNames::MaxArticleSize );
1053 if ( !isset( $contentInfo[
'text'] ) ) {
1054 throw new MWException(
'Missing text field in import.' );
1061 if ( ( !isset( $contentInfo[
'model'] ) ||
1062 in_array( $contentInfo[
'model'], [
1070 strlen( $contentInfo[
'text'] ) > $maxArticleSize * 1024
1074 "the revision with ID $revisionId" :
1076 ) .
" exceeds the maximum allowable size ({$maxArticleSize} KiB)" );
1079 $role = $contentInfo[
'role'] ?? SlotRecord::MAIN;
1080 $model = $contentInfo[
'model'] ?? $this->getDefaultContentModel( $title, $role );
1081 $handler = $this->getContentHandler( $model );
1083 $text = $handler->importTransform( $contentInfo[
'text'] );
1085 return $handler->unserializeContent( $text );
1094 private function processRevision( $pageInfo, $revisionInfo ) {
1097 $revId = $revisionInfo[
'id'] ?? 0;
1099 $revision->setID( $revisionInfo[
'id'] );
1102 $title = $pageInfo[
'_title'];
1103 $revision->setTitle( $title );
1105 $content = $this->makeContent( $title, $revId, $revisionInfo );
1106 $revision->setContent( SlotRecord::MAIN,
$content );
1108 foreach ( $revisionInfo[
'content'] ?? [] as $slotInfo ) {
1109 if ( !isset( $slotInfo[
'role'] ) ) {
1110 throw new MWException(
"Missing role for imported slot." );
1113 $content = $this->makeContent( $title, $revId, $slotInfo );
1114 $revision->setContent( $slotInfo[
'role'],
$content );
1116 $revision->setTimestamp( $revisionInfo[
'timestamp'] ??
wfTimestampNow() );
1118 if ( isset( $revisionInfo[
'comment'] ) ) {
1119 $revision->setComment( $revisionInfo[
'comment'] );
1122 if ( isset( $revisionInfo[
'minor'] ) ) {
1123 $revision->setMinor(
true );
1125 if ( isset( $revisionInfo[
'contributor'][
'username'] ) ) {
1126 $revision->setUsername(
1127 $this->externalUserNames->applyPrefix( $revisionInfo[
'contributor'][
'username'] )
1129 } elseif ( isset( $revisionInfo[
'contributor'][
'ip'] ) ) {
1130 $revision->setUserIP( $revisionInfo[
'contributor'][
'ip'] );
1132 $revision->setUsername( $this->externalUserNames->addPrefix(
'Unknown user' ) );
1134 if ( isset( $revisionInfo[
'sha1'] ) ) {
1135 $revision->setSha1Base36( $revisionInfo[
'sha1'] );
1137 $revision->setNoUpdates( $this->mNoUpdates );
1139 return $this->revisionCallback( $revision );
1146 private function handleUpload( &$pageInfo ) {
1147 $this->
debug(
"Enter upload handler" );
1150 $normalFields = [
'timestamp',
'comment',
'filename',
'text',
1151 'src',
'size',
'sha1base36',
'archivename',
'rel' ];
1155 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
1156 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
1157 $this->reader->localName ==
'upload' ) {
1161 $tag = $this->reader->localName;
1163 if ( !$this->hookRunner->onImportHandleUploadXMLTag( $this, $pageInfo ) ) {
1165 } elseif ( in_array( $tag, $normalFields ) ) {
1167 } elseif ( $tag ==
'contributor' ) {
1168 $uploadInfo[
'contributor'] = $this->handleContributor();
1169 } elseif ( $tag ==
'contents' ) {
1171 $encoding = $this->reader->getAttribute(
'encoding' );
1172 if ( $encoding ===
'base64' ) {
1173 $uploadInfo[
'fileSrc'] = $this->dumpTemp( base64_decode( $contents ) );
1174 $uploadInfo[
'isTempSrc'] =
true;
1176 } elseif ( $tag !=
'#text' ) {
1177 $this->
warn(
"Unhandled upload XML tag $tag" );
1182 if ( $this->mImageBasePath && isset( $uploadInfo[
'rel'] ) ) {
1183 $path =
"{$this->mImageBasePath}/{$uploadInfo['rel']}";
1184 if ( file_exists(
$path ) ) {
1185 $uploadInfo[
'fileSrc'] =
$path;
1186 $uploadInfo[
'isTempSrc'] =
false;
1190 if ( $this->mImportUploads ) {
1191 return $this->processUpload( $pageInfo, $uploadInfo );
1199 private function dumpTemp( $contents ) {
1200 $filename = tempnam(
wfTempDir(),
'importupload' );
1201 file_put_contents( $filename, $contents );
1210 private function processUpload( $pageInfo, $uploadInfo ) {
1212 $revId = $pageInfo[
'id'];
1213 $title = $pageInfo[
'_title'];
1215 $uploadInfo[
'text'] = $uploadInfo[
'text'] ??
'';
1216 $content = $this->makeContent( $title, $revId, $uploadInfo );
1218 $revision->setTitle( $title );
1219 $revision->setID( $revId );
1220 $revision->setTimestamp( $uploadInfo[
'timestamp'] );
1221 $revision->setContent( SlotRecord::MAIN,
$content );
1222 $revision->setFilename( $uploadInfo[
'filename'] );
1223 if ( isset( $uploadInfo[
'archivename'] ) ) {
1224 $revision->setArchiveName( $uploadInfo[
'archivename'] );
1226 $revision->setSrc( $uploadInfo[
'src'] );
1227 if ( isset( $uploadInfo[
'fileSrc'] ) ) {
1228 $revision->setFileSrc( $uploadInfo[
'fileSrc'],
1229 !empty( $uploadInfo[
'isTempSrc'] )
1232 if ( isset( $uploadInfo[
'sha1base36'] ) ) {
1233 $revision->setSha1Base36( $uploadInfo[
'sha1base36'] );
1235 $revision->setSize( intval( $uploadInfo[
'size'] ) );
1236 $revision->setComment( $uploadInfo[
'comment'] );
1238 if ( isset( $uploadInfo[
'contributor'][
'username'] ) ) {
1239 $revision->setUsername(
1240 $this->externalUserNames->applyPrefix( $uploadInfo[
'contributor'][
'username'] )
1242 } elseif ( isset( $uploadInfo[
'contributor'][
'ip'] ) ) {
1243 $revision->setUserIP( $uploadInfo[
'contributor'][
'ip'] );
1245 $revision->setNoUpdates( $this->mNoUpdates );
1247 return call_user_func( $this->mUploadCallback, $revision );
1253 private function handleContributor() {
1254 $this->
debug(
"Enter contributor handler." );
1256 if ( $this->reader->isEmptyElement ) {
1260 $fields = [
'id',
'ip',
'username' ];
1263 while ( $this->reader->read() ) {
1264 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
1265 $this->reader->localName ==
'contributor' ) {
1269 $tag = $this->reader->localName;
1271 if ( in_array( $tag, $fields ) ) {
1284 private function processTitle( $text, $ns =
null ) {
1285 if ( $this->foreignNamespaces ===
null ) {
1287 $this->contentLanguage
1291 $this->foreignNamespaces );
1294 $foreignTitle = $foreignTitleFactory->createForeignTitle( $text,
1297 $title = $this->importTitleFactory->createTitleFromForeignTitle(
1300 $commandLineMode = $this->config->get(
'CommandLineMode' );
1301 if ( $title ===
null ) {
1302 # Invalid page title? Ignore the page
1303 $this->
notice(
'import-error-invalid', $foreignTitle->getFullText() );
1311 } elseif ( !$commandLineMode ) {
1314 if ( !$this->permissionManager->userCan(
'edit', $user, $title ) ) {
1315 # Do not import if the importing wiki user cannot edit this page
1322 return [ $title, $foreignTitle ];
1329 private function getContentHandler( $model ) {
1330 return $this->contentHandlerFactory->getContentHandler( $model );
1339 private function getDefaultContentModel( $title, $role ) {
1340 return $this->slotRoleRegistry
1341 ->getRoleHandler( $role )
1342 ->getDefaultModel( $title );
1349 private function openReader() {
1353 $oldDisable = @libxml_disable_entity_loader(
false );
1355 if ( PHP_VERSION_ID >= 80000 ) {
1357 $reader = XMLReader::open(
1358 'uploadsource://' . $this->sourceAdapterId,
null, LIBXML_PARSEHUGE );
1359 if ( $reader instanceof XMLReader ) {
1360 $this->reader = $reader;
1367 $this->reader =
new XMLReader;
1368 $status = $this->reader->open(
1369 'uploadsource://' . $this->sourceAdapterId,
null, LIBXML_PARSEHUGE );
1372 $error = libxml_get_last_error();
1374 @libxml_disable_entity_loader( $oldDisable );
1376 'Encountered an internal error while initializing WikiImporter object: ' . $error->message
1380 @libxml_disable_entity_loader( $oldDisable );
1386 private function syntaxCheckXML() {
1390 AtEase::suppressWarnings();
1391 $oldDisable = libxml_disable_entity_loader(
false );
1393 while ( $this->reader->read() );
1394 $error = libxml_get_last_error();
1396 $errorMessage =
'XML error at line ' . $error->line .
': ' . $error->message;
1397 wfDebug( __METHOD__ .
': Invalid xml found - ' . $errorMessage );
1401 libxml_disable_entity_loader( $oldDisable );
1402 AtEase::restoreWarnings();
1403 $this->reader->close();
1408 $this->openReader();