MediaWiki
REL1_20
|
00001 <?php 00032 class SpecialImport extends SpecialPage { 00033 00034 private $interwiki = false; 00035 private $namespace; 00036 private $rootpage = ''; 00037 private $frompage = ''; 00038 private $logcomment= false; 00039 private $history = true; 00040 private $includeTemplates = false; 00041 private $pageLinkDepth; 00042 00046 public function __construct() { 00047 parent::__construct( 'Import', 'import' ); 00048 global $wgImportTargetNamespace; 00049 $this->namespace = $wgImportTargetNamespace; 00050 } 00051 00055 function execute( $par ) { 00056 $this->setHeaders(); 00057 $this->outputHeader(); 00058 00059 $user = $this->getUser(); 00060 if ( !$user->isAllowedAny( 'import', 'importupload' ) ) { 00061 throw new PermissionsError( 'import' ); 00062 } 00063 00064 # @todo Allow Title::getUserPermissionsErrors() to take an array 00065 # @todo FIXME: Title::checkSpecialsAndNSPermissions() has a very wierd expectation of what 00066 # getUserPermissionsErrors() might actually be used for, hence the 'ns-specialprotected' 00067 $errors = wfMergeErrorArrays( 00068 $this->getTitle()->getUserPermissionsErrors( 00069 'import', $user, true, 00070 array( 'ns-specialprotected', 'badaccess-group0', 'badaccess-groups' ) 00071 ), 00072 $this->getTitle()->getUserPermissionsErrors( 00073 'importupload', $user, true, 00074 array( 'ns-specialprotected', 'badaccess-group0', 'badaccess-groups' ) 00075 ) 00076 ); 00077 00078 if ( $errors ) { 00079 throw new PermissionsError( 'import', $errors ); 00080 } 00081 00082 $this->checkReadOnly(); 00083 00084 $request = $this->getRequest(); 00085 if ( $request->wasPosted() && $request->getVal( 'action' ) == 'submit' ) { 00086 $this->doImport(); 00087 } 00088 $this->showForm(); 00089 } 00090 00094 private function doImport() { 00095 global $wgImportSources, $wgExportMaxLinkDepth; 00096 00097 $isUpload = false; 00098 $request = $this->getRequest(); 00099 $this->namespace = $request->getIntOrNull( 'namespace' ); 00100 $sourceName = $request->getVal( "source" ); 00101 00102 $this->logcomment = $request->getText( 'log-comment' ); 00103 $this->pageLinkDepth = $wgExportMaxLinkDepth == 0 ? 0 : $request->getIntOrNull( 'pagelink-depth' ); 00104 $this->rootpage = $request->getText( 'rootpage' ); 00105 00106 $user = $this->getUser(); 00107 if ( !$user->matchEditToken( $request->getVal( 'editToken' ) ) ) { 00108 $source = Status::newFatal( 'import-token-mismatch' ); 00109 } elseif ( $sourceName == 'upload' ) { 00110 $isUpload = true; 00111 if( $user->isAllowed( 'importupload' ) ) { 00112 $source = ImportStreamSource::newFromUpload( "xmlimport" ); 00113 } else { 00114 throw new PermissionsError( 'importupload' ); 00115 } 00116 } elseif ( $sourceName == "interwiki" ) { 00117 if( !$user->isAllowed( 'import' ) ){ 00118 throw new PermissionsError( 'import' ); 00119 } 00120 $this->interwiki = $request->getVal( 'interwiki' ); 00121 if ( !in_array( $this->interwiki, $wgImportSources ) ) { 00122 $source = Status::newFatal( "import-invalid-interwiki" ); 00123 } else { 00124 $this->history = $request->getCheck( 'interwikiHistory' ); 00125 $this->frompage = $request->getText( "frompage" ); 00126 $this->includeTemplates = $request->getCheck( 'interwikiTemplates' ); 00127 $source = ImportStreamSource::newFromInterwiki( 00128 $this->interwiki, 00129 $this->frompage, 00130 $this->history, 00131 $this->includeTemplates, 00132 $this->pageLinkDepth ); 00133 } 00134 } else { 00135 $source = Status::newFatal( "importunknownsource" ); 00136 } 00137 00138 $out = $this->getOutput(); 00139 if( !$source->isGood() ) { 00140 $out->wrapWikiMsg( "<p class=\"error\">\n$1\n</p>", array( 'importfailed', $source->getWikiText() ) ); 00141 } else { 00142 $importer = new WikiImporter( $source->value ); 00143 if( !is_null( $this->namespace ) ) { 00144 $importer->setTargetNamespace( $this->namespace ); 00145 } 00146 if( !is_null( $this->rootpage ) ) { 00147 $statusRootPage = $importer->setTargetRootPage( $this->rootpage ); 00148 if( !$statusRootPage->isGood() ) { 00149 $out->wrapWikiMsg( "<p class=\"error\">\n$1\n</p>", array( 'import-options-wrong', $statusRootPage->getWikiText(), count( $statusRootPage->getErrorsArray() ) ) ); 00150 return; 00151 } 00152 } 00153 00154 $out->addWikiMsg( "importstart" ); 00155 00156 $reporter = new ImportReporter( $importer, $isUpload, $this->interwiki , $this->logcomment); 00157 $reporter->setContext( $this->getContext() ); 00158 $exception = false; 00159 00160 $reporter->open(); 00161 try { 00162 $importer->doImport(); 00163 } catch ( MWException $e ) { 00164 $exception = $e; 00165 } 00166 $result = $reporter->close(); 00167 00168 if ( $exception ) { 00169 # No source or XML parse error 00170 $out->wrapWikiMsg( "<p class=\"error\">\n$1\n</p>", array( 'importfailed', $exception->getMessage() ) ); 00171 } elseif( !$result->isGood() ) { 00172 # Zero revisions 00173 $out->wrapWikiMsg( "<p class=\"error\">\n$1\n</p>", array( 'importfailed', $result->getWikiText() ) ); 00174 } else { 00175 # Success! 00176 $out->addWikiMsg( 'importsuccess' ); 00177 } 00178 $out->addHTML( '<hr />' ); 00179 } 00180 } 00181 00182 private function showForm() { 00183 global $wgImportSources, $wgExportMaxLinkDepth; 00184 00185 $action = $this->getTitle()->getLocalUrl( array( 'action' => 'submit' ) ); 00186 $user = $this->getUser(); 00187 $out = $this->getOutput(); 00188 00189 if( $user->isAllowed( 'importupload' ) ) { 00190 $out->addHTML( 00191 Xml::fieldset( $this->msg( 'import-upload' )->text() ). 00192 Xml::openElement( 'form', array( 'enctype' => 'multipart/form-data', 'method' => 'post', 00193 'action' => $action, 'id' => 'mw-import-upload-form' ) ) . 00194 $this->msg( 'importtext' )->parseAsBlock() . 00195 Html::hidden( 'action', 'submit' ) . 00196 Html::hidden( 'source', 'upload' ) . 00197 Xml::openElement( 'table', array( 'id' => 'mw-import-table' ) ) . 00198 00199 "<tr> 00200 <td class='mw-label'>" . 00201 Xml::label( $this->msg( 'import-upload-filename' )->text(), 'xmlimport' ) . 00202 "</td> 00203 <td class='mw-input'>" . 00204 Xml::input( 'xmlimport', 50, '', array( 'type' => 'file' ) ) . ' ' . 00205 "</td> 00206 </tr> 00207 <tr> 00208 <td class='mw-label'>" . 00209 Xml::label( $this->msg( 'import-comment' )->text(), 'mw-import-comment' ) . 00210 "</td> 00211 <td class='mw-input'>" . 00212 Xml::input( 'log-comment', 50, '', 00213 array( 'id' => 'mw-import-comment', 'type' => 'text' ) ) . ' ' . 00214 "</td> 00215 </tr> 00216 <tr> 00217 <td class='mw-label'>" . 00218 Xml::label( $this->msg( 'import-interwiki-rootpage' )->text(), 'mw-interwiki-rootpage' ) . 00219 "</td> 00220 <td class='mw-input'>" . 00221 Xml::input( 'rootpage', 50, $this->rootpage, 00222 array( 'id' => 'mw-interwiki-rootpage', 'type' => 'text' ) ) . ' ' . 00223 "</td> 00224 </tr> 00225 <tr> 00226 <td></td> 00227 <td class='mw-submit'>" . 00228 Xml::submitButton( $this->msg( 'uploadbtn' )->text() ) . 00229 "</td> 00230 </tr>" . 00231 Xml::closeElement( 'table' ). 00232 Html::hidden( 'editToken', $user->getEditToken() ) . 00233 Xml::closeElement( 'form' ) . 00234 Xml::closeElement( 'fieldset' ) 00235 ); 00236 } else { 00237 if( empty( $wgImportSources ) ) { 00238 $out->addWikiMsg( 'importnosources' ); 00239 } 00240 } 00241 00242 if( $user->isAllowed( 'import' ) && !empty( $wgImportSources ) ) { 00243 # Show input field for import depth only if $wgExportMaxLinkDepth > 0 00244 $importDepth = ''; 00245 if( $wgExportMaxLinkDepth > 0 ) { 00246 $importDepth = "<tr> 00247 <td class='mw-label'>" . 00248 $this->msg( 'export-pagelinks' )->parse() . 00249 "</td> 00250 <td class='mw-input'>" . 00251 Xml::input( 'pagelink-depth', 3, 0 ) . 00252 "</td> 00253 </tr>"; 00254 } 00255 00256 $out->addHTML( 00257 Xml::fieldset( $this->msg( 'importinterwiki' )->text() ) . 00258 Xml::openElement( 'form', array( 'method' => 'post', 'action' => $action, 'id' => 'mw-import-interwiki-form' ) ) . 00259 $this->msg( 'import-interwiki-text' )->parseAsBlock() . 00260 Html::hidden( 'action', 'submit' ) . 00261 Html::hidden( 'source', 'interwiki' ) . 00262 Html::hidden( 'editToken', $user->getEditToken() ) . 00263 Xml::openElement( 'table', array( 'id' => 'mw-import-table' ) ) . 00264 "<tr> 00265 <td class='mw-label'>" . 00266 Xml::label( $this->msg( 'import-interwiki-source' )->text(), 'interwiki' ) . 00267 "</td> 00268 <td class='mw-input'>" . 00269 Xml::openElement( 'select', array( 'name' => 'interwiki' ) ) 00270 ); 00271 foreach( $wgImportSources as $prefix ) { 00272 $selected = ( $this->interwiki === $prefix ) ? ' selected="selected"' : ''; 00273 $out->addHTML( Xml::option( $prefix, $prefix, $selected ) ); 00274 } 00275 00276 $out->addHTML( 00277 Xml::closeElement( 'select' ) . 00278 Xml::input( 'frompage', 50, $this->frompage ) . 00279 "</td> 00280 </tr> 00281 <tr> 00282 <td> 00283 </td> 00284 <td class='mw-input'>" . 00285 Xml::checkLabel( $this->msg( 'import-interwiki-history' )->text(), 'interwikiHistory', 'interwikiHistory', $this->history ) . 00286 "</td> 00287 </tr> 00288 <tr> 00289 <td> 00290 </td> 00291 <td class='mw-input'>" . 00292 Xml::checkLabel( $this->msg( 'import-interwiki-templates' )->text(), 'interwikiTemplates', 'interwikiTemplates', $this->includeTemplates ) . 00293 "</td> 00294 </tr> 00295 $importDepth 00296 <tr> 00297 <td class='mw-label'>" . 00298 Xml::label( $this->msg( 'import-interwiki-namespace' )->text(), 'namespace' ) . 00299 "</td> 00300 <td class='mw-input'>" . 00301 Html::namespaceSelector( 00302 array( 00303 'selected' => $this->namespace, 00304 'all' => '', 00305 ), array( 00306 'name' => 'namespace', 00307 'id' => 'namespace', 00308 'class' => 'namespaceselector', 00309 ) 00310 ) . 00311 "</td> 00312 </tr> 00313 <tr> 00314 <td class='mw-label'>" . 00315 Xml::label( $this->msg( 'import-comment' )->text(), 'mw-interwiki-comment' ) . 00316 "</td> 00317 <td class='mw-input'>" . 00318 Xml::input( 'log-comment', 50, '', 00319 array( 'id' => 'mw-interwiki-comment', 'type' => 'text' ) ) . ' ' . 00320 "</td> 00321 </tr> 00322 <tr> 00323 <td class='mw-label'>" . 00324 Xml::label( $this->msg( 'import-interwiki-rootpage' )->text(), 'mw-interwiki-rootpage' ) . 00325 "</td> 00326 <td class='mw-input'>" . 00327 Xml::input( 'rootpage', 50, $this->rootpage, 00328 array( 'id' => 'mw-interwiki-rootpage', 'type' => 'text' ) ) . ' ' . 00329 "</td> 00330 </tr> 00331 <tr> 00332 <td> 00333 </td> 00334 <td class='mw-submit'>" . 00335 Xml::submitButton( $this->msg( 'import-interwiki-submit' )->text(), Linker::tooltipAndAccesskeyAttribs( 'import' ) ) . 00336 "</td> 00337 </tr>" . 00338 Xml::closeElement( 'table' ). 00339 Xml::closeElement( 'form' ) . 00340 Xml::closeElement( 'fieldset' ) 00341 ); 00342 } 00343 } 00344 } 00345 00350 class ImportReporter extends ContextSource { 00351 private $reason=false; 00352 private $mOriginalLogCallback = null; 00353 private $mOriginalPageOutCallback = null; 00354 private $mLogItemCount = 0; 00355 00356 function __construct( $importer, $upload, $interwiki , $reason=false ) { 00357 $this->mOriginalPageOutCallback = 00358 $importer->setPageOutCallback( array( $this, 'reportPage' ) ); 00359 $this->mOriginalLogCallback = 00360 $importer->setLogItemCallback( array( $this, 'reportLogItem' ) ); 00361 $importer->setNoticeCallback( array( $this, 'reportNotice' ) ); 00362 $this->mPageCount = 0; 00363 $this->mIsUpload = $upload; 00364 $this->mInterwiki = $interwiki; 00365 $this->reason = $reason; 00366 } 00367 00368 function open() { 00369 $this->getOutput()->addHTML( "<ul>\n" ); 00370 } 00371 00372 function reportNotice( $msg, array $params ) { 00373 $this->getOutput()->addHTML( Html::element( 'li', array(), $this->msg( $msg, $params )->text() ) ); 00374 } 00375 00376 function reportLogItem( /* ... */ ) { 00377 $this->mLogItemCount++; 00378 if ( is_callable( $this->mOriginalLogCallback ) ) { 00379 call_user_func_array( $this->mOriginalLogCallback, func_get_args() ); 00380 } 00381 } 00382 00391 function reportPage( $title, $origTitle, $revisionCount, $successCount, $pageInfo ) { 00392 $args = func_get_args(); 00393 call_user_func_array( $this->mOriginalPageOutCallback, $args ); 00394 00395 if ( $title === null ) { 00396 # Invalid or non-importable title; a notice is already displayed 00397 return; 00398 } 00399 00400 $this->mPageCount++; 00401 00402 if( $successCount > 0 ) { 00403 $this->getOutput()->addHTML( "<li>" . Linker::linkKnown( $title ) . " " . 00404 $this->msg( 'import-revision-count' )->numParams( $successCount )->escaped() . 00405 "</li>\n" 00406 ); 00407 00408 $log = new LogPage( 'import' ); 00409 if( $this->mIsUpload ) { 00410 $detail = $this->msg( 'import-logentry-upload-detail' )->numParams( 00411 $successCount )->inContentLanguage()->text(); 00412 if ( $this->reason ) { 00413 $detail .= $this->msg( 'colon-separator' )->inContentLanguage()->text() . $this->reason; 00414 } 00415 $log->addEntry( 'upload', $title, $detail ); 00416 } else { 00417 $interwiki = '[[:' . $this->mInterwiki . ':' . 00418 $origTitle->getPrefixedText() . ']]'; 00419 $detail = $this->msg( 'import-logentry-interwiki-detail' )->numParams( 00420 $successCount )->params( $interwiki )->inContentLanguage()->text(); 00421 if ( $this->reason ) { 00422 $detail .= $this->msg( 'colon-separator' )->inContentLanguage()->text() . $this->reason; 00423 } 00424 $log->addEntry( 'interwiki', $title, $detail ); 00425 } 00426 00427 $comment = $detail; // quick 00428 $dbw = wfGetDB( DB_MASTER ); 00429 $latest = $title->getLatestRevID(); 00430 $nullRevision = Revision::newNullRevision( $dbw, $title->getArticleID(), $comment, true ); 00431 if (!is_null($nullRevision)) { 00432 $nullRevision->insertOn( $dbw ); 00433 $page = WikiPage::factory( $title ); 00434 # Update page record 00435 $page->updateRevisionOn( $dbw, $nullRevision ); 00436 wfRunHooks( 'NewRevisionFromEditComplete', array( $page, $nullRevision, $latest, $this->getUser() ) ); 00437 } 00438 } else { 00439 $this->getOutput()->addHTML( "<li>" . Linker::linkKnown( $title ) . " " . 00440 $this->msg( 'import-nonewrevisions' )->escaped() . "</li>\n" ); 00441 } 00442 } 00443 00444 function close() { 00445 $out = $this->getOutput(); 00446 if ( $this->mLogItemCount > 0 ) { 00447 $msg = $this->msg( 'imported-log-entries' )->numParams( $this->mLogItemCount )->parse(); 00448 $out->addHTML( Xml::tags( 'li', null, $msg ) ); 00449 } elseif( $this->mPageCount == 0 && $this->mLogItemCount == 0 ) { 00450 $out->addHTML( "</ul>\n" ); 00451 return Status::newFatal( 'importnopages' ); 00452 } 00453 $out->addHTML( "</ul>\n" ); 00454 00455 return Status::newGood( $this->mPageCount ); 00456 } 00457 }