67 private $sourceAdapterId;
70 private $foreignNamespaces =
null;
73 private $mLogItemCallback;
76 private $mUploadCallback;
79 private $mRevisionCallback;
82 private $mPageCallback;
85 private $mSiteInfoCallback;
88 private $mPageOutCallback;
91 private $mNoticeCallback;
97 private $mImportUploads;
100 private $mImageBasePath;
103 private $mNoUpdates =
false;
106 private $pageOffset = 0;
112 private $countableCache = [];
115 private $disableStatisticsUpdate =
false;
127 private Language $contentLanguage;
143 Language $contentLanguage,
151 $this->performer = $performer;
152 $this->config = $config;
153 $this->hookRunner =
new HookRunner( $hookContainer );
154 $this->contentLanguage = $contentLanguage;
155 $this->namespaceInfo = $namespaceInfo;
156 $this->titleFactory = $titleFactory;
157 $this->wikiPageFactory = $wikiPageFactory;
158 $this->uploadRevisionImporter = $uploadRevisionImporter;
159 $this->contentHandlerFactory = $contentHandlerFactory;
160 $this->slotRoleRegistry = $slotRoleRegistry;
162 if ( !in_array(
'uploadsource', stream_get_wrappers() ) ) {
163 stream_wrapper_register(
'uploadsource', UploadSourceAdapter::class );
177 $this->contentLanguage,
178 $this->namespaceInfo,
188 return $this->reader;
195 $this->
debug(
"FAILURE: $err" );
196 wfDebug(
"WikiImporter XML error: $err" );
203 if ( $this->mDebug ) {
211 public function warn( $data ) {
220 if ( is_callable( $this->mNoticeCallback ) ) {
221 call_user_func( $this->mNoticeCallback, $msg,
$params );
234 $this->mDebug = $debug;
242 $this->mNoUpdates = $noupdates;
252 $this->pageOffset = $nthPage;
262 return wfSetVar( $this->mNoticeCallback, $callback );
271 $previous = $this->mPageCallback;
272 $this->mPageCallback = $callback;
286 $previous = $this->mPageOutCallback;
287 $this->mPageOutCallback = $callback;
297 $previous = $this->mRevisionCallback;
298 $this->mRevisionCallback = $callback;
308 $previous = $this->mUploadCallback;
309 $this->mUploadCallback = $callback;
319 $previous = $this->mLogItemCallback;
320 $this->mLogItemCallback = $callback;
330 $previous = $this->mSiteInfoCallback;
331 $this->mSiteInfoCallback = $callback;
341 $this->importTitleFactory = $factory;
350 if ( $namespace ===
null ) {
354 $this->contentLanguage,
355 $this->namespaceInfo,
362 $this->namespaceInfo->exists( intval( $namespace ) )
364 $namespace = intval( $namespace );
367 $this->namespaceInfo,
384 $status = Status::newGood();
385 $nsInfo = $this->namespaceInfo;
386 if ( $rootpage ===
null ) {
390 $this->contentLanguage,
395 } elseif ( $rootpage !==
'' ) {
396 $rootpage = rtrim( $rootpage,
'/' );
397 $title = Title::newFromText( $rootpage );
399 if ( !$title || $title->isExternal() ) {
400 $status->fatal(
'import-rootpage-invalid' );
401 } elseif ( !$nsInfo->hasSubpages( $title->getNamespace() ) ) {
402 $displayNSText = $title->getNamespace() ===
NS_MAIN
404 : $this->contentLanguage->getNsText( $title->getNamespace() );
405 $status->fatal(
'import-rootpage-nosubpage', $displayNSText );
425 $this->mImageBasePath = $dir;
432 $this->mImportUploads = $import;
441 $this->externalUserNames =
new ExternalUserNames( $usernamePrefix, $assignKnownUsers );
459 $title = $titleAndForeignTitle[0];
460 $page = $this->wikiPageFactory->newFromTitle( $title );
461 $this->countableCache[
'title_' . $title->getPrefixedText()] = $page->isCountable();
471 if ( !$revision->getContentHandler()->canBeUsedOn( $revision->getTitle() ) ) {
472 $this->
notice(
'import-error-bad-location',
473 $revision->getTitle()->getPrefixedText(),
475 $revision->getModel(),
476 $revision->getFormat()
483 return $revision->importOldRevision();
485 $this->
notice(
'import-error-unserialize',
486 $revision->getTitle()->getPrefixedText(),
488 $revision->getModel(),
489 $revision->getFormat()
502 return $revision->importLogItem();
511 $status = $this->uploadRevisionImporter->import( $revision );
512 return $status->isGood();
525 $sRevCount, $pageInfo
534 $page = $this->wikiPageFactory->newFromTitle( $pageIdentity );
536 $page->loadPageData( IDBAccessObject::READ_LATEST );
537 $rev = $page->getRevisionRecord();
538 if ( $rev ===
null ) {
540 wfDebug( __METHOD__ .
': Skipping article count adjustment for ' . $pageIdentity .
541 ' because WikiPage::getRevisionRecord() returned null' );
543 $update = $page->newPageUpdater( $this->performer )->prepareUpdate();
544 $countKey =
'title_' . CacheKeyHelper::getKeyForPage( $pageIdentity );
545 $countable = $update->isCountable();
546 if ( array_key_exists( $countKey, $this->countableCache ) &&
547 $countable != $this->countableCache[$countKey] ) {
548 DeferredUpdates::addUpdate( SiteStatsUpdate::factory( [
549 'articles' => ( (
int)$countable - (
int)$this->countableCache[$countKey] )
555 $title = Title::newFromPageIdentity( $pageIdentity );
556 return $this->hookRunner->onAfterImportPage( $title, $foreignTitle,
557 $revCount, $sRevCount, $pageInfo );
565 private function siteInfoCallback( $siteInfo ) {
566 if ( isset( $this->mSiteInfoCallback ) ) {
567 return call_user_func_array(
568 $this->mSiteInfoCallback,
581 if ( isset( $this->mPageCallback ) ) {
582 call_user_func( $this->mPageCallback, $title );
594 private function pageOutCallback(
PageIdentity $pageIdentity, $foreignTitle, $revCount,
595 $sucCount, $pageInfo ) {
596 if ( isset( $this->mPageOutCallback ) ) {
597 call_user_func_array( $this->mPageOutCallback, func_get_args() );
606 private function revisionCallback( $revision ) {
607 if ( isset( $this->mRevisionCallback ) ) {
608 return call_user_func_array(
609 $this->mRevisionCallback,
622 private function logItemCallback( $revision ) {
623 if ( isset( $this->mLogItemCallback ) ) {
624 return call_user_func_array(
625 $this->mLogItemCallback,
640 return $this->reader->getAttribute( $attr ) ??
'';
651 if ( $this->reader->isEmptyElement ) {
655 while ( $this->reader->read() ) {
656 switch ( $this->reader->nodeType ) {
657 case XMLReader::TEXT:
658 case XMLReader::CDATA:
659 case XMLReader::SIGNIFICANT_WHITESPACE:
660 $buffer .= $this->reader->value;
662 case XMLReader::END_ELEMENT:
667 $this->reader->close();
677 $this->syntaxCheckXML();
683 $oldDisable = @libxml_disable_entity_loader(
true );
685 $this->reader->read();
687 if ( $this->reader->localName !=
'mediawiki' ) {
689 @libxml_disable_entity_loader( $oldDisable );
690 $error = libxml_get_last_error();
692 throw new NormalizedException(
"XML error at line {line}: {message}", [
693 'line' => $error->line,
694 'message' => $error->message,
697 throw new UnexpectedValueException(
698 "Expected '<mediawiki>' tag, got '<{$this->reader->localName}>' tag."
702 $this->
debug(
"<mediawiki> tag is correct." );
704 $this->
debug(
"Starting primary dump processing loop." );
706 $keepReading = $this->reader->read();
709 while ( $keepReading ) {
710 $tag = $this->reader->localName;
711 if ( $this->pageOffset ) {
712 if ( $tag ===
'page' ) {
715 if ( $pageCount < $this->pageOffset ) {
716 $keepReading = $this->reader->next();
720 $type = $this->reader->nodeType;
722 if ( !$this->hookRunner->onImportHandleToplevelXMLTag( $this ) ) {
724 } elseif ( $tag ==
'mediawiki' && $type == XMLReader::END_ELEMENT ) {
726 } elseif ( $tag ==
'siteinfo' ) {
727 $this->handleSiteInfo();
728 } elseif ( $tag ==
'page' ) {
730 } elseif ( $tag ==
'logitem' ) {
731 $this->handleLogItem();
732 } elseif ( $tag !=
'#text' ) {
733 $this->
warn(
"Unhandled top-level XML tag $tag" );
739 $keepReading = $this->reader->next();
741 $this->
debug(
"Skip" );
743 $keepReading = $this->reader->read();
748 @libxml_disable_entity_loader( $oldDisable );
749 $this->reader->close();
755 private function handleSiteInfo() {
756 $this->debug(
"Enter site info handler." );
760 $normalFields = [
'sitename',
'base',
'generator',
'case' ];
762 while ( $this->reader->read() ) {
763 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
764 $this->reader->localName ==
'siteinfo' ) {
768 $tag = $this->reader->localName;
770 if ( $tag ==
'namespace' ) {
773 } elseif ( in_array( $tag, $normalFields ) ) {
778 $siteInfo[
'_namespaces'] = $this->foreignNamespaces;
779 $this->siteInfoCallback( $siteInfo );
782 private function handleLogItem() {
783 $this->
debug(
"Enter log item handler." );
787 $normalFields = [
'id',
'comment',
'type',
'action',
'timestamp',
788 'logtitle',
'params' ];
790 while ( $this->reader->read() ) {
791 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
792 $this->reader->localName ==
'logitem' ) {
796 $tag = $this->reader->localName;
798 if ( !$this->hookRunner->onImportHandleLogItemXMLTag( $this, $logInfo ) ) {
800 } elseif ( in_array( $tag, $normalFields ) ) {
802 } elseif ( $tag ==
'contributor' ) {
803 $logInfo[
'contributor'] = $this->handleContributor();
804 } elseif ( $tag !=
'#text' ) {
805 $this->
warn(
"Unhandled log-item XML tag $tag" );
809 $this->processLogItem( $logInfo );
816 private function processLogItem( $logInfo ) {
819 if ( isset( $logInfo[
'id'] ) ) {
820 $revision->setID( $logInfo[
'id'] );
822 $revision->setType( $logInfo[
'type'] );
823 $revision->setAction( $logInfo[
'action'] );
824 if ( isset( $logInfo[
'timestamp'] ) ) {
825 $revision->setTimestamp( $logInfo[
'timestamp'] );
827 if ( isset( $logInfo[
'params'] ) ) {
828 $revision->setParams( $logInfo[
'params'] );
830 if ( isset( $logInfo[
'logtitle'] ) ) {
833 $revision->setTitle( Title::newFromText( $logInfo[
'logtitle'] ) );
836 $revision->setNoUpdates( $this->mNoUpdates );
838 if ( isset( $logInfo[
'comment'] ) ) {
839 $revision->setComment( $logInfo[
'comment'] );
842 if ( isset( $logInfo[
'contributor'][
'username'] ) ) {
843 $revision->setUsername(
844 $this->externalUserNames->applyPrefix( $logInfo[
'contributor'][
'username'] )
846 } elseif ( isset( $logInfo[
'contributor'][
'ip'] ) ) {
847 $revision->setUserIP( $logInfo[
'contributor'][
'ip'] );
849 $revision->setUsername( $this->externalUserNames->addPrefix(
'Unknown user' ) );
852 return $this->logItemCallback( $revision );
855 private function handlePage() {
857 $this->
debug(
"Enter page handler." );
858 $pageInfo = [
'revisionCount' => 0,
'successfulRevisionCount' => 0 ];
861 $normalFields = [
'title',
'ns',
'id',
'redirect',
'restrictions' ];
866 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
867 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
868 $this->reader->localName ==
'page' ) {
874 $tag = $this->reader->localName;
879 } elseif ( !$this->hookRunner->onImportHandlePageXMLTag( $this, $pageInfo ) ) {
881 } elseif ( in_array( $tag, $normalFields ) ) {
889 if ( $tag ==
'redirect' ) {
894 } elseif ( $tag ==
'revision' || $tag ==
'upload' ) {
895 if ( !isset( $title ) ) {
896 $title = $this->processTitle( $pageInfo[
'title'],
897 $pageInfo[
'ns'] ??
null );
900 if ( is_array( $title ) ) {
902 [ $pageInfo[
'_title'], $foreignTitle ] = $title;
910 if ( $tag ==
'revision' ) {
911 $this->handleRevision( $pageInfo );
913 $this->handleUpload( $pageInfo );
916 } elseif ( $tag !=
'#text' ) {
917 $this->
warn(
"Unhandled page XML tag $tag" );
927 if ( array_key_exists(
'_title', $pageInfo ) ) {
929 $title = $pageInfo[
'_title'];
930 $this->pageOutCallback(
934 $pageInfo[
'revisionCount'],
935 $pageInfo[
'successfulRevisionCount'],
944 private function handleRevision( &$pageInfo ) {
945 $this->
debug(
"Enter revision handler" );
948 $normalFields = [
'id',
'parentid',
'timestamp',
'comment',
'minor',
'origin',
949 'model',
'format',
'text',
'sha1' ];
953 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
954 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
955 $this->reader->localName ==
'revision' ) {
959 $tag = $this->reader->localName;
961 if ( !$this->hookRunner->onImportHandleRevisionXMLTag(
962 $this, $pageInfo, $revisionInfo )
965 } elseif ( in_array( $tag, $normalFields ) ) {
967 } elseif ( $tag ==
'content' ) {
969 $revisionInfo[$tag][] = $this->handleContent();
970 } elseif ( $tag ==
'contributor' ) {
971 $revisionInfo[
'contributor'] = $this->handleContributor();
972 } elseif ( $tag !=
'#text' ) {
973 $this->
warn(
"Unhandled revision XML tag $tag" );
978 $pageInfo[
'revisionCount']++;
979 if ( $this->processRevision( $pageInfo, $revisionInfo ) ) {
980 $pageInfo[
'successfulRevisionCount']++;
984 private function handleContent() {
985 $this->
debug(
"Enter content handler" );
988 $normalFields = [
'role',
'origin',
'model',
'format',
'text' ];
992 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
993 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
994 $this->reader->localName ==
'content' ) {
998 $tag = $this->reader->localName;
1000 if ( !$this->hookRunner->onImportHandleContentXMLTag(
1001 $this, $contentInfo )
1004 } elseif ( in_array( $tag, $normalFields ) ) {
1006 } elseif ( $tag !=
'#text' ) {
1007 $this->
warn(
"Unhandled content XML tag $tag" );
1012 return $contentInfo;
1022 private function makeContent(
PageIdentity $page, $revisionId, $contentInfo ) {
1023 $maxArticleSize = $this->config->get( MainConfigNames::MaxArticleSize );
1025 if ( !isset( $contentInfo[
'text'] ) ) {
1026 throw new InvalidArgumentException(
'Missing text field in import.' );
1033 if ( ( !isset( $contentInfo[
'model'] ) ||
1034 in_array( $contentInfo[
'model'], [
1042 strlen( $contentInfo[
'text'] ) > $maxArticleSize * 1024
1044 throw new RuntimeException(
'The text of ' .
1046 "the revision with ID $revisionId" :
1048 ) .
" exceeds the maximum allowable size ({$maxArticleSize} KiB)" );
1051 $role = $contentInfo[
'role'] ?? SlotRecord::MAIN;
1052 $model = $contentInfo[
'model'] ?? $this->slotRoleRegistry
1053 ->getRoleHandler( $role )
1054 ->getDefaultModel( $page );
1055 $handler = $this->contentHandlerFactory->getContentHandler( $model );
1057 $text = $handler->importTransform( $contentInfo[
'text'] );
1059 return $handler->unserializeContent( $text );
1067 private function processRevision( $pageInfo, $revisionInfo ) {
1070 $revId = $revisionInfo[
'id'] ?? 0;
1072 $revision->setID( $revisionInfo[
'id'] );
1075 $title = $pageInfo[
'_title'];
1076 $revision->setTitle( $title );
1078 $content = $this->makeContent( $title, $revId, $revisionInfo );
1079 $revision->setContent( SlotRecord::MAIN, $content );
1081 foreach ( $revisionInfo[
'content'] ?? [] as $slotInfo ) {
1082 if ( !isset( $slotInfo[
'role'] ) ) {
1083 throw new RuntimeException(
"Missing role for imported slot." );
1086 $content = $this->makeContent( $title, $revId, $slotInfo );
1087 $revision->setContent( $slotInfo[
'role'], $content );
1089 $revision->setTimestamp( $revisionInfo[
'timestamp'] ??
wfTimestampNow() );
1091 if ( isset( $revisionInfo[
'comment'] ) ) {
1092 $revision->setComment( $revisionInfo[
'comment'] );
1095 if ( isset( $revisionInfo[
'minor'] ) ) {
1096 $revision->setMinor(
true );
1098 if ( isset( $revisionInfo[
'contributor'][
'username'] ) ) {
1099 $revision->setUsername(
1100 $this->externalUserNames->applyPrefix( $revisionInfo[
'contributor'][
'username'] )
1102 } elseif ( isset( $revisionInfo[
'contributor'][
'ip'] ) ) {
1103 $revision->setUserIP( $revisionInfo[
'contributor'][
'ip'] );
1105 $revision->setUsername( $this->externalUserNames->addPrefix(
'Unknown user' ) );
1107 if ( isset( $revisionInfo[
'sha1'] ) ) {
1108 $revision->setSha1Base36( $revisionInfo[
'sha1'] );
1110 $revision->setNoUpdates( $this->mNoUpdates );
1112 return $this->revisionCallback( $revision );
1119 private function handleUpload( &$pageInfo ) {
1120 $this->
debug(
"Enter upload handler" );
1123 $normalFields = [
'timestamp',
'comment',
'filename',
'text',
1124 'src',
'size',
'sha1base36',
'archivename',
'rel' ];
1128 while ( $skip ? $this->reader->next() : $this->reader->read() ) {
1129 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
1130 $this->reader->localName ==
'upload' ) {
1134 $tag = $this->reader->localName;
1136 if ( !$this->hookRunner->onImportHandleUploadXMLTag( $this, $pageInfo ) ) {
1138 } elseif ( in_array( $tag, $normalFields ) ) {
1140 } elseif ( $tag ==
'contributor' ) {
1141 $uploadInfo[
'contributor'] = $this->handleContributor();
1142 } elseif ( $tag ==
'contents' ) {
1144 $encoding = $this->reader->getAttribute(
'encoding' );
1145 if ( $encoding ===
'base64' ) {
1146 $uploadInfo[
'fileSrc'] = $this->dumpTemp( base64_decode( $contents ) );
1147 $uploadInfo[
'isTempSrc'] =
true;
1149 } elseif ( $tag !=
'#text' ) {
1150 $this->
warn(
"Unhandled upload XML tag $tag" );
1155 if ( $this->mImageBasePath && isset( $uploadInfo[
'rel'] ) ) {
1156 $path =
"{$this->mImageBasePath}/{$uploadInfo['rel']}";
1157 if ( file_exists(
$path ) ) {
1158 $uploadInfo[
'fileSrc'] =
$path;
1159 $uploadInfo[
'isTempSrc'] =
false;
1163 if ( $this->mImportUploads ) {
1164 return $this->processUpload( $pageInfo, $uploadInfo );
1172 private function dumpTemp( $contents ) {
1173 $filename = tempnam(
wfTempDir(),
'importupload' );
1174 file_put_contents( $filename, $contents );
1183 private function processUpload( $pageInfo, $uploadInfo ) {
1185 $revId = $pageInfo[
'id'];
1186 $title = $pageInfo[
'_title'];
1188 $uploadInfo[
'text'] ??=
'';
1189 $content = $this->makeContent( $title, $revId, $uploadInfo );
1191 $revision->setTitle( $title );
1192 $revision->setID( $revId );
1193 $revision->setTimestamp( $uploadInfo[
'timestamp'] );
1194 $revision->setContent( SlotRecord::MAIN, $content );
1195 $revision->setFilename( $uploadInfo[
'filename'] );
1196 if ( isset( $uploadInfo[
'archivename'] ) ) {
1197 $revision->setArchiveName( $uploadInfo[
'archivename'] );
1199 $revision->setSrc( $uploadInfo[
'src'] );
1200 if ( isset( $uploadInfo[
'fileSrc'] ) ) {
1201 $revision->setFileSrc( $uploadInfo[
'fileSrc'],
1202 !empty( $uploadInfo[
'isTempSrc'] )
1205 if ( isset( $uploadInfo[
'sha1base36'] ) ) {
1206 $revision->setSha1Base36( $uploadInfo[
'sha1base36'] );
1208 $revision->setSize( intval( $uploadInfo[
'size'] ) );
1209 $revision->setComment( $uploadInfo[
'comment'] );
1211 if ( isset( $uploadInfo[
'contributor'][
'username'] ) ) {
1212 $revision->setUsername(
1213 $this->externalUserNames->applyPrefix( $uploadInfo[
'contributor'][
'username'] )
1215 } elseif ( isset( $uploadInfo[
'contributor'][
'ip'] ) ) {
1216 $revision->setUserIP( $uploadInfo[
'contributor'][
'ip'] );
1218 $revision->setNoUpdates( $this->mNoUpdates );
1220 return call_user_func( $this->mUploadCallback, $revision );
1226 private function handleContributor() {
1227 $this->
debug(
"Enter contributor handler." );
1229 if ( $this->reader->isEmptyElement ) {
1233 $fields = [
'id',
'ip',
'username' ];
1236 while ( $this->reader->read() ) {
1237 if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
1238 $this->reader->localName ==
'contributor' ) {
1242 $tag = $this->reader->localName;
1244 if ( in_array( $tag, $fields ) ) {
1257 private function processTitle( $text, $ns =
null ) {
1258 if ( $this->foreignNamespaces ===
null ) {
1260 $this->contentLanguage
1264 $this->foreignNamespaces );
1267 $foreignTitle = $foreignTitleFactory->createForeignTitle( $text,
1270 $title = $this->importTitleFactory->createTitleFromForeignTitle(
1273 if ( $title ===
null ) {
1274 # Invalid page title? Ignore the page
1275 $this->
notice(
'import-error-invalid', $foreignTitle->getFullText() );
1277 } elseif ( $title->isExternal() ) {
1278 $this->
notice(
'import-error-interwiki', $title->getPrefixedText() );
1280 } elseif ( !$title->canExist() ) {
1281 $this->
notice(
'import-error-special', $title->getPrefixedText() );
1283 } elseif ( !$this->performer->definitelyCan(
'edit', $title ) ) {
1284 # Do not import if the importing wiki user cannot edit this page
1285 $this->
notice(
'import-error-edit', $title->getPrefixedText() );
1289 return [ $title, $foreignTitle ];
1296 private function openReader() {
1300 $oldDisable = @libxml_disable_entity_loader(
false );
1302 if ( PHP_VERSION_ID >= 80000 ) {
1304 $reader = XMLReader::open(
1305 'uploadsource://' . $this->sourceAdapterId,
null, LIBXML_PARSEHUGE );
1306 if ( $reader instanceof XMLReader ) {
1307 $this->reader = $reader;
1314 $this->reader =
new XMLReader;
1315 $status = $this->reader->open(
1316 'uploadsource://' . $this->sourceAdapterId,
null, LIBXML_PARSEHUGE );
1319 $error = libxml_get_last_error();
1321 @libxml_disable_entity_loader( $oldDisable );
1322 throw new RuntimeException(
1323 'Encountered an internal error while initializing WikiImporter object: ' . $error->message
1327 @libxml_disable_entity_loader( $oldDisable );
1333 private function syntaxCheckXML() {
1337 AtEase::suppressWarnings();
1338 $oldDisable = libxml_disable_entity_loader(
false );
1340 while ( $this->reader->read() );
1341 $error = libxml_get_last_error();
1343 $errorMessage =
'XML error at line ' . $error->line .
': ' . $error->message;
1344 wfDebug( __METHOD__ .
': Invalid xml found - ' . $errorMessage );
1345 throw new RuntimeException( $errorMessage );
1348 libxml_disable_entity_loader( $oldDisable );
1349 AtEase::restoreWarnings();
1350 $this->reader->close();
1355 $this->openReader();