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