64 private $sourceAdapterId;
67 private $foreignNamespaces =
null;
70 private $mLogItemCallback;
73 private $mUploadCallback;
76 private $mRevisionCallback;
79 private $mPageCallback;
82 private $mSiteInfoCallback;
85 private $mPageOutCallback;
88 private $mNoticeCallback;
94 private $mImportUploads;
97 private $mImageBasePath;
100 private $mNoUpdates =
false;
103 private $pageOffset = 0;
109 private $countableCache = [];
112 private $disableStatisticsUpdate =
false;
148 $this->performer = $performer;
149 $this->config = $config;
150 $this->hookRunner =
new HookRunner( $hookContainer );
151 $this->contentLanguage = $contentLanguage;
152 $this->namespaceInfo = $namespaceInfo;
153 $this->titleFactory = $titleFactory;
154 $this->wikiPageFactory = $wikiPageFactory;
155 $this->uploadRevisionImporter = $uploadRevisionImporter;
156 $this->contentHandlerFactory = $contentHandlerFactory;
157 $this->slotRoleRegistry = $slotRoleRegistry;
159 if ( !in_array(
'uploadsource', stream_get_wrappers() ) ) {
160 stream_wrapper_register(
'uploadsource', UploadSourceAdapter::class );
174 $this->contentLanguage,
175 $this->namespaceInfo,
185 return $this->reader;
192 $this->
debug(
"FAILURE: $err" );
193 wfDebug(
"WikiImporter XML error: $err" );
200 if ( $this->mDebug ) {
208 public function warn( $data ) {
218 public function notice( $msg, ...$params ) {
219 if ( is_callable( $this->mNoticeCallback ) ) {
220 ( $this->mNoticeCallback )( $msg, $params );
233 $this->mDebug = $debug;
241 $this->mNoUpdates = $noupdates;
251 $this->pageOffset = $nthPage;
261 return wfSetVar( $this->mNoticeCallback, $callback );
270 $previous = $this->mPageCallback;
271 $this->mPageCallback = $callback;
285 $previous = $this->mPageOutCallback;
286 $this->mPageOutCallback = $callback;
296 $previous = $this->mRevisionCallback;
297 $this->mRevisionCallback = $callback;
307 $previous = $this->mUploadCallback;
308 $this->mUploadCallback = $callback;
318 $previous = $this->mLogItemCallback;
319 $this->mLogItemCallback = $callback;
329 $previous = $this->mSiteInfoCallback;
330 $this->mSiteInfoCallback = $callback;
340 $this->importTitleFactory = $factory;
349 if ( $namespace ===
null ) {
353 $this->contentLanguage,
354 $this->namespaceInfo,
361 $this->namespaceInfo->exists( intval( $namespace ) )
363 $namespace = intval( $namespace );
366 $this->namespaceInfo,
383 $status = Status::newGood();
384 $nsInfo = $this->namespaceInfo;
385 if ( $rootpage ===
null ) {
389 $this->contentLanguage,
394 } elseif ( $rootpage !==
'' ) {
395 $rootpage = rtrim( $rootpage,
'/' );
396 $title = Title::newFromText( $rootpage );
398 if ( !$title || $title->isExternal() ) {
399 $status->fatal(
'import-rootpage-invalid' );
400 } elseif ( !$nsInfo->hasSubpages( $title->getNamespace() ) ) {
401 $displayNSText = $title->getNamespace() ===
NS_MAIN
403 : $this->contentLanguage->getNsText( $title->getNamespace() );
404 $status->fatal(
'import-rootpage-nosubpage', $displayNSText );
424 $this->mImageBasePath = $dir;
431 $this->mImportUploads = $import;
440 $this->externalUserNames =
new ExternalUserNames( $usernamePrefix, $assignKnownUsers );
458 $title = $titleAndForeignTitle[0];
459 $page = $this->wikiPageFactory->newFromTitle( $title );
460 $this->countableCache[
'title_' . $title->getPrefixedText()] = $page->isCountable();
470 if ( !$revision->getContentHandler()->canBeUsedOn( $revision->getTitle() ) ) {
471 $this->
notice(
'import-error-bad-location',
472 $revision->getTitle()->getPrefixedText(),
474 $revision->getModel(),
475 $revision->getFormat()
482 return $revision->importOldRevision();
484 $this->
notice(
'import-error-unserialize',
485 $revision->getTitle()->getPrefixedText(),
487 $revision->getModel(),
488 $revision->getFormat()
501 return $revision->importLogItem();
510 $status = $this->uploadRevisionImporter->import( $revision );
511 return $status->isGood();
524 $sRevCount, $pageInfo
533 $page = $this->wikiPageFactory->newFromTitle( $pageIdentity );
535 $page->loadPageData( IDBAccessObject::READ_LATEST );
536 $rev = $page->getRevisionRecord();
537 if ( $rev ===
null ) {
539 wfDebug( __METHOD__ .
': Skipping article count adjustment for ' . $pageIdentity .
540 ' because WikiPage::getRevisionRecord() returned null' );
542 $update = $page->newPageUpdater( $this->performer )->prepareUpdate();
543 $countKey =
'title_' . CacheKeyHelper::getKeyForPage( $pageIdentity );
544 $countable = $update->isCountable();
545 if ( array_key_exists( $countKey, $this->countableCache ) &&
546 $countable != $this->countableCache[$countKey] ) {
547 DeferredUpdates::addUpdate( SiteStatsUpdate::factory( [
548 'articles' => ( (
int)$countable - (
int)$this->countableCache[$countKey] )
554 $title = Title::newFromPageIdentity( $pageIdentity );
555 return $this->hookRunner->onAfterImportPage( $title, $foreignTitle,
556 $revCount, $sRevCount, $pageInfo );
564 private function siteInfoCallback( $siteInfo ) {
565 if ( $this->mSiteInfoCallback ) {
566 return ( $this->mSiteInfoCallback )( $siteInfo, $this );
577 if ( $this->mPageCallback ) {
578 ( $this->mPageCallback )( $title );
590 private function pageOutCallback(
PageIdentity $pageIdentity, $foreignTitle, $revCount,
591 $sucCount, $pageInfo ) {
592 if ( $this->mPageOutCallback ) {
593 ( $this->mPageOutCallback )( $pageIdentity, $foreignTitle, $revCount, $sucCount, $pageInfo );
602 private function revisionCallback( $revision ) {
603 if ( $this->mRevisionCallback ) {
604 return ( $this->mRevisionCallback )( $revision, $this );
615 private function logItemCallback( $revision ) {
616 if ( $this->mLogItemCallback ) {
617 return ( $this->mLogItemCallback )( $revision, $this );
630 return $this->reader->getAttribute( $attr ) ??
'';
641 if ( $this->reader->isEmptyElement ) {
645 while ( $this->reader->read() ) {
646 switch ( $this->reader->nodeType ) {
647 case XMLReader::TEXT:
648 case XMLReader::CDATA:
649 case XMLReader::SIGNIFICANT_WHITESPACE:
650 $buffer .= $this->reader->value;
652 case XMLReader::END_ELEMENT:
657 $this->reader->close();
667 $this->syntaxCheckXML();
673 $oldDisable = @libxml_disable_entity_loader(
true );
675 $this->reader->read();
677 if ( $this->reader->localName !=
'mediawiki' ) {
679 @libxml_disable_entity_loader( $oldDisable );
680 $error = libxml_get_last_error();
682 throw new NormalizedException(
"XML error at line {line}: {message}", [
683 'line' => $error->line,
684 'message' => $error->message,
687 throw new UnexpectedValueException(
688 "Expected '<mediawiki>' tag, got '<{$this->reader->localName}>' tag."
692 $this->
debug(
"<mediawiki> tag is correct." );
694 $this->
debug(
"Starting primary dump processing loop." );
696 $keepReading = $this->reader->read();
699 while ( $keepReading ) {
700 $tag = $this->reader->localName;
701 if ( $this->pageOffset ) {
702 if ( $tag ===
'page' ) {
705 if ( $pageCount < $this->pageOffset ) {
706 $keepReading = $this->reader->next();
710 $type = $this->reader->nodeType;
712 if ( !$this->hookRunner->onImportHandleToplevelXMLTag( $this ) ) {
714 } elseif ( $tag ==
'mediawiki' && $type == XMLReader::END_ELEMENT ) {
716 } elseif ( $tag ==
'siteinfo' ) {
717 $this->handleSiteInfo();
718 } elseif ( $tag ==
'page' ) {
720 } elseif ( $tag ==
'logitem' ) {
721 $this->handleLogItem();
722 } elseif ( $tag !=
'#text' ) {
723 $this->
warn(
"Unhandled top-level XML tag $tag" );
729 $keepReading = $this->reader->next();
731 $this->
debug(
"Skip" );
733 $keepReading = $this->reader->read();
738 @libxml_disable_entity_loader( $oldDisable );
739 $this->reader->close();
745 private function handleSiteInfo() {
746 $this->
debug(
"Enter site info handler." );
750 $normalFields = [
'sitename',
'base',
'generator',
'case' ];
752 while ( $this->reader->read() ) {
753 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
754 $this->reader->localName ==
'siteinfo' ) {
758 $tag = $this->reader->localName;
760 if ( $tag ==
'namespace' ) {
763 } elseif ( in_array( $tag, $normalFields ) ) {
768 $siteInfo[
'_namespaces'] = $this->foreignNamespaces;
769 $this->siteInfoCallback( $siteInfo );
772 private function handleLogItem() {
773 $this->
debug(
"Enter log item handler." );
777 $normalFields = [
'id',
'comment',
'type',
'action',
'timestamp',
778 'logtitle',
'params' ];
780 while ( $this->reader->read() ) {
781 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
782 $this->reader->localName ==
'logitem' ) {
786 $tag = $this->reader->localName;
788 if ( !$this->hookRunner->onImportHandleLogItemXMLTag( $this, $logInfo ) ) {
790 } elseif ( in_array( $tag, $normalFields ) ) {
792 } elseif ( $tag ==
'contributor' ) {
793 $logInfo[
'contributor'] = $this->handleContributor();
794 } elseif ( $tag !=
'#text' ) {
795 $this->
warn(
"Unhandled log-item XML tag $tag" );
799 $this->processLogItem( $logInfo );
806 private function processLogItem( $logInfo ) {
807 $revision =
new WikiRevision();
809 if ( isset( $logInfo[
'id'] ) ) {
810 $revision->setID( $logInfo[
'id'] );
812 $revision->setType( $logInfo[
'type'] );
813 $revision->setAction( $logInfo[
'action'] );
814 if ( isset( $logInfo[
'timestamp'] ) ) {
815 $revision->setTimestamp( $logInfo[
'timestamp'] );
817 if ( isset( $logInfo[
'params'] ) ) {
818 $revision->setParams( $logInfo[
'params'] );
820 if ( isset( $logInfo[
'logtitle'] ) ) {
823 $revision->setTitle( Title::newFromText( $logInfo[
'logtitle'] ) );
826 $revision->setNoUpdates( $this->mNoUpdates );
828 if ( isset( $logInfo[
'comment'] ) ) {
829 $revision->setComment( $logInfo[
'comment'] );
832 if ( isset( $logInfo[
'contributor'][
'username'] ) ) {
833 $revision->setUsername(
834 $this->externalUserNames->applyPrefix( $logInfo[
'contributor'][
'username'] )
836 } elseif ( isset( $logInfo[
'contributor'][
'ip'] ) ) {
837 $revision->setUserIP( $logInfo[
'contributor'][
'ip'] );
839 $revision->setUsername( $this->externalUserNames->addPrefix(
'Unknown user' ) );
842 return $this->logItemCallback( $revision );
845 private function handlePage() {
847 $this->
debug(
"Enter page handler." );
848 $pageInfo = [
'revisionCount' => 0,
'successfulRevisionCount' => 0 ];
851 $normalFields = [
'title',
'ns',
'id',
'redirect',
'restrictions' ];
856 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
857 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
858 $this->reader->localName ==
'page' ) {
864 $tag = $this->reader->localName;
869 } elseif ( !$this->hookRunner->onImportHandlePageXMLTag( $this, $pageInfo ) ) {
871 } elseif ( in_array( $tag, $normalFields ) ) {
879 if ( $tag ==
'redirect' ) {
884 } elseif ( $tag ==
'revision' || $tag ==
'upload' ) {
885 if ( !isset( $title ) ) {
886 $title = $this->processTitle( $pageInfo[
'title'],
887 $pageInfo[
'ns'] ??
null );
890 if ( is_array( $title ) ) {
892 [ $pageInfo[
'_title'], $foreignTitle ] = $title;
900 if ( $tag ==
'revision' ) {
901 $this->handleRevision( $pageInfo );
903 $this->handleUpload( $pageInfo );
906 } elseif ( $tag !=
'#text' ) {
907 $this->
warn(
"Unhandled page XML tag $tag" );
917 if ( array_key_exists(
'_title', $pageInfo ) ) {
919 $title = $pageInfo[
'_title'];
920 $this->pageOutCallback(
924 $pageInfo[
'revisionCount'],
925 $pageInfo[
'successfulRevisionCount'],
934 private function handleRevision( &$pageInfo ) {
935 $this->
debug(
"Enter revision handler" );
938 $normalFields = [
'id',
'parentid',
'timestamp',
'comment',
'minor',
'origin',
939 'model',
'format',
'text',
'sha1' ];
943 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
944 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
945 $this->reader->localName ==
'revision' ) {
949 $tag = $this->reader->localName;
951 if ( !$this->hookRunner->onImportHandleRevisionXMLTag(
952 $this, $pageInfo, $revisionInfo )
955 } elseif ( in_array( $tag, $normalFields ) ) {
957 } elseif ( $tag ==
'content' ) {
959 $revisionInfo[$tag][] = $this->handleContent();
960 } elseif ( $tag ==
'contributor' ) {
961 $revisionInfo[
'contributor'] = $this->handleContributor();
962 } elseif ( $tag !=
'#text' ) {
963 $this->
warn(
"Unhandled revision XML tag $tag" );
968 $pageInfo[
'revisionCount']++;
969 if ( $this->processRevision( $pageInfo, $revisionInfo ) ) {
970 $pageInfo[
'successfulRevisionCount']++;
974 private function handleContent(): array {
975 $this->
debug(
"Enter content handler" );
978 $normalFields = [
'role',
'origin',
'model',
'format',
'text' ];
982 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
983 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
984 $this->reader->localName ==
'content' ) {
988 $tag = $this->reader->localName;
990 if ( !$this->hookRunner->onImportHandleContentXMLTag(
991 $this, $contentInfo )
994 } elseif ( in_array( $tag, $normalFields ) ) {
996 } elseif ( $tag !=
'#text' ) {
997 $this->
warn(
"Unhandled content XML tag $tag" );
1002 return $contentInfo;
1012 private function makeContent( PageIdentity $page, $revisionId, $contentInfo ) {
1015 if ( !isset( $contentInfo[
'text'] ) ) {
1016 throw new InvalidArgumentException(
'Missing text field in import.' );
1023 if ( ( !isset( $contentInfo[
'model'] ) ||
1024 in_array( $contentInfo[
'model'], [
1032 strlen( $contentInfo[
'text'] ) > $maxArticleSize * 1024
1034 throw new RuntimeException(
'The text of ' .
1036 "the revision with ID $revisionId" :
1038 ) .
" exceeds the maximum allowable size ({$maxArticleSize} KiB)" );
1041 $role = $contentInfo[
'role'] ?? SlotRecord::MAIN;
1042 $model = $contentInfo[
'model'] ?? $this->slotRoleRegistry
1043 ->getRoleHandler( $role )
1044 ->getDefaultModel( $page );
1045 $handler = $this->contentHandlerFactory->getContentHandler( $model );
1047 $text = $handler->importTransform( $contentInfo[
'text'] );
1049 return $handler->unserializeContent( $text );
1057 private function processRevision( $pageInfo, $revisionInfo ) {
1058 $revision =
new WikiRevision();
1060 $revId = $revisionInfo[
'id'] ?? 0;
1062 $revision->setID( $revisionInfo[
'id'] );
1065 $title = $pageInfo[
'_title'];
1066 $revision->setTitle( $title );
1068 $content = $this->makeContent( $title, $revId, $revisionInfo );
1069 $revision->setContent( SlotRecord::MAIN, $content );
1071 foreach ( $revisionInfo[
'content'] ?? [] as $slotInfo ) {
1072 if ( !isset( $slotInfo[
'role'] ) ) {
1073 throw new RuntimeException(
"Missing role for imported slot." );
1076 $content = $this->makeContent( $title, $revId, $slotInfo );
1077 $revision->setContent( $slotInfo[
'role'], $content );
1079 $revision->setTimestamp( $revisionInfo[
'timestamp'] ??
wfTimestampNow() );
1081 if ( isset( $revisionInfo[
'comment'] ) ) {
1082 $revision->setComment( $revisionInfo[
'comment'] );
1085 if ( isset( $revisionInfo[
'minor'] ) ) {
1086 $revision->setMinor(
true );
1088 if ( isset( $revisionInfo[
'contributor'][
'username'] ) ) {
1089 $revision->setUsername(
1090 $this->externalUserNames->applyPrefix( $revisionInfo[
'contributor'][
'username'] )
1092 } elseif ( isset( $revisionInfo[
'contributor'][
'ip'] ) ) {
1093 $revision->setUserIP( $revisionInfo[
'contributor'][
'ip'] );
1095 $revision->setUsername( $this->externalUserNames->addPrefix(
'Unknown user' ) );
1097 if ( isset( $revisionInfo[
'sha1'] ) ) {
1098 $revision->setSha1Base36( $revisionInfo[
'sha1'] );
1100 $revision->setNoUpdates( $this->mNoUpdates );
1102 return $this->revisionCallback( $revision );
1109 private function handleUpload( &$pageInfo ) {
1110 $this->debug(
"Enter upload handler" );
1113 $normalFields = [
'timestamp',
'comment',
'filename',
'text',
1114 'src',
'size',
'sha1base36',
'archivename',
'rel' ];
1118 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
1119 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
1120 $this->reader->localName ==
'upload' ) {
1124 $tag = $this->reader->localName;
1126 if ( !$this->hookRunner->onImportHandleUploadXMLTag( $this, $pageInfo ) ) {
1128 } elseif ( in_array( $tag, $normalFields ) ) {
1129 $uploadInfo[$tag] = $this->nodeContents();
1130 } elseif ( $tag ==
'contributor' ) {
1131 $uploadInfo[
'contributor'] = $this->handleContributor();
1132 } elseif ( $tag ==
'contents' ) {
1133 $contents = $this->nodeContents();
1134 $encoding = $this->reader->getAttribute(
'encoding' );
1135 if ( $encoding ===
'base64' ) {
1136 $uploadInfo[
'fileSrc'] = $this->dumpTemp( base64_decode( $contents ) );
1137 $uploadInfo[
'isTempSrc'] =
true;
1139 } elseif ( $tag !=
'#text' ) {
1140 $this->warn(
"Unhandled upload XML tag $tag" );
1145 if ( $this->mImageBasePath && isset( $uploadInfo[
'rel'] ) ) {
1146 $path =
"{$this->mImageBasePath}/{$uploadInfo['rel']}";
1147 if ( file_exists(
$path ) ) {
1148 $uploadInfo[
'fileSrc'] =
$path;
1149 $uploadInfo[
'isTempSrc'] =
false;
1153 if ( $this->mImportUploads ) {
1154 return $this->processUpload( $pageInfo, $uploadInfo );
1162 private function dumpTemp( $contents ) {
1163 $filename = tempnam(
wfTempDir(),
'importupload' );
1164 file_put_contents( $filename, $contents );
1173 private function processUpload( $pageInfo, $uploadInfo ) {
1174 $revision =
new WikiRevision();
1175 $revId = $pageInfo[
'id'];
1176 $title = $pageInfo[
'_title'];
1178 $uploadInfo[
'text'] ??=
'';
1179 $content = $this->makeContent( $title, $revId, $uploadInfo );
1181 $revision->setTitle( $title );
1182 $revision->setID( $revId );
1183 $revision->setTimestamp( $uploadInfo[
'timestamp'] );
1184 $revision->setContent( SlotRecord::MAIN, $content );
1185 $revision->setFilename( $uploadInfo[
'filename'] );
1186 if ( isset( $uploadInfo[
'archivename'] ) ) {
1187 $revision->setArchiveName( $uploadInfo[
'archivename'] );
1189 $revision->setSrc( $uploadInfo[
'src'] );
1190 if ( isset( $uploadInfo[
'fileSrc'] ) ) {
1191 $revision->setFileSrc( $uploadInfo[
'fileSrc'],
1192 !empty( $uploadInfo[
'isTempSrc'] )
1195 if ( isset( $uploadInfo[
'sha1base36'] ) ) {
1196 $revision->setSha1Base36( $uploadInfo[
'sha1base36'] );
1198 $revision->setSize( intval( $uploadInfo[
'size'] ) );
1199 $revision->setComment( $uploadInfo[
'comment'] );
1201 if ( isset( $uploadInfo[
'contributor'][
'username'] ) ) {
1202 $revision->setUsername(
1203 $this->externalUserNames->applyPrefix( $uploadInfo[
'contributor'][
'username'] )
1205 } elseif ( isset( $uploadInfo[
'contributor'][
'ip'] ) ) {
1206 $revision->setUserIP( $uploadInfo[
'contributor'][
'ip'] );
1208 $revision->setNoUpdates( $this->mNoUpdates );
1210 return ( $this->mUploadCallback )( $revision );
1216 private function handleContributor() {
1217 $this->debug(
"Enter contributor handler." );
1219 if ( $this->reader->isEmptyElement ) {
1223 $fields = [
'id',
'ip',
'username' ];
1226 while ( $this->reader->read() ) {
1227 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
1228 $this->reader->localName ==
'contributor' ) {
1232 $tag = $this->reader->localName;
1234 if ( in_array( $tag, $fields ) ) {
1235 $info[$tag] = $this->nodeContents();
1247 private function processTitle( $text, $ns =
null ) {
1248 if ( $this->foreignNamespaces ===
null ) {
1249 $foreignTitleFactory =
new NaiveForeignTitleFactory(
1250 $this->contentLanguage
1253 $foreignTitleFactory =
new NamespaceAwareForeignTitleFactory(
1254 $this->foreignNamespaces );
1257 $foreignTitle = $foreignTitleFactory->createForeignTitle( $text,
1260 $title = $this->importTitleFactory->createTitleFromForeignTitle(
1263 if ( $title ===
null ) {
1264 # Invalid page title? Ignore the page
1265 $this->notice(
'import-error-invalid', $foreignTitle->getFullText() );
1267 } elseif ( $title->isExternal() ) {
1268 $this->notice(
'import-error-interwiki', $title->getPrefixedText() );
1270 } elseif ( !$title->canExist() ) {
1271 $this->notice(
'import-error-special', $title->getPrefixedText() );
1273 } elseif ( !$this->performer->definitelyCan(
'edit', $title ) ) {
1274 # Do not import if the importing wiki user cannot edit this page
1275 $this->notice(
'import-error-edit', $title->getPrefixedText() );
1279 return [ $title, $foreignTitle ];
1285 private function openReader() {
1289 $oldDisable = @libxml_disable_entity_loader(
false );
1292 $reader = XMLReader::open(
1293 'uploadsource://' . $this->sourceAdapterId,
null, LIBXML_PARSEHUGE );
1294 if ( $reader instanceof XMLReader ) {
1295 $this->reader = $reader;
1301 $error = libxml_get_last_error();
1303 @libxml_disable_entity_loader( $oldDisable );
1304 throw new RuntimeException(
1305 'Encountered an internal error while initializing WikiImporter object: ' . $error->message
1309 @libxml_disable_entity_loader( $oldDisable );
1315 private function syntaxCheckXML() {
1319 AtEase::suppressWarnings();
1320 $oldDisable = libxml_disable_entity_loader(
false );
1322 while ( $this->reader->read() );
1323 $error = libxml_get_last_error();
1325 $errorMessage =
'XML error at line ' . $error->line .
': ' . $error->message;
1326 wfDebug( __METHOD__ .
': Invalid xml found - ' . $errorMessage );
1327 throw new RuntimeException( $errorMessage );
1330 libxml_disable_entity_loader( $oldDisable );
1331 AtEase::restoreWarnings();
1332 $this->reader->close();
1337 $this->openReader();