[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Implements Special:Movepage 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 * http://www.gnu.org/copyleft/gpl.html 19 * 20 * @file 21 * @ingroup SpecialPage 22 */ 23 24 /** 25 * A special page that allows users to change page titles 26 * 27 * @ingroup SpecialPage 28 */ 29 class MovePageForm extends UnlistedSpecialPage { 30 /** @var Title */ 31 protected $oldTitle; 32 33 /** @var Title */ 34 protected $newTitle; 35 36 37 /** @var string Text input */ 38 protected $reason; 39 40 // Checks 41 42 /** @var bool */ 43 protected $moveTalk; 44 45 /** @var bool */ 46 protected $deleteAndMove; 47 48 /** @var bool */ 49 protected $moveSubpages; 50 51 /** @var bool */ 52 protected $fixRedirects; 53 54 /** @var bool */ 55 protected $leaveRedirect; 56 57 /** @var bool */ 58 protected $moveOverShared; 59 60 private $watch = false; 61 62 public function __construct() { 63 parent::__construct( 'Movepage' ); 64 } 65 66 public function execute( $par ) { 67 $this->checkReadOnly(); 68 69 $this->setHeaders(); 70 $this->outputHeader(); 71 72 $request = $this->getRequest(); 73 $target = !is_null( $par ) ? $par : $request->getVal( 'target' ); 74 75 // Yes, the use of getVal() and getText() is wanted, see bug 20365 76 77 $oldTitleText = $request->getVal( 'wpOldTitle', $target ); 78 $this->oldTitle = Title::newFromText( $oldTitleText ); 79 80 if ( is_null( $this->oldTitle ) ) { 81 throw new ErrorPageError( 'notargettitle', 'notargettext' ); 82 } 83 if ( !$this->oldTitle->exists() ) { 84 throw new ErrorPageError( 'nopagetitle', 'nopagetext' ); 85 } 86 87 $newTitleTextMain = $request->getText( 'wpNewTitleMain' ); 88 $newTitleTextNs = $request->getInt( 'wpNewTitleNs', $this->oldTitle->getNamespace() ); 89 // Backwards compatibility for forms submitting here from other sources 90 // which is more common than it should be.. 91 $newTitleText_bc = $request->getText( 'wpNewTitle' ); 92 $this->newTitle = strlen( $newTitleText_bc ) > 0 93 ? Title::newFromText( $newTitleText_bc ) 94 : Title::makeTitleSafe( $newTitleTextNs, $newTitleTextMain ); 95 96 $user = $this->getUser(); 97 98 # Check rights 99 $permErrors = $this->oldTitle->getUserPermissionsErrors( 'move', $user ); 100 if ( count( $permErrors ) ) { 101 // Auto-block user's IP if the account was "hard" blocked 102 $user->spreadAnyEditBlock(); 103 throw new PermissionsError( 'move', $permErrors ); 104 } 105 106 $def = !$request->wasPosted(); 107 108 $this->reason = $request->getText( 'wpReason' ); 109 $this->moveTalk = $request->getBool( 'wpMovetalk', $def ); 110 $this->fixRedirects = $request->getBool( 'wpFixRedirects', $def ); 111 $this->leaveRedirect = $request->getBool( 'wpLeaveRedirect', $def ); 112 $this->moveSubpages = $request->getBool( 'wpMovesubpages', false ); 113 $this->deleteAndMove = $request->getBool( 'wpDeleteAndMove' ) && $request->getBool( 'wpConfirm' ); 114 $this->moveOverShared = $request->getBool( 'wpMoveOverSharedFile', false ); 115 $this->watch = $request->getCheck( 'wpWatch' ) && $user->isLoggedIn(); 116 117 if ( 'submit' == $request->getVal( 'action' ) && $request->wasPosted() 118 && $user->matchEditToken( $request->getVal( 'wpEditToken' ) ) 119 ) { 120 $this->doSubmit(); 121 } else { 122 $this->showForm( array() ); 123 } 124 } 125 126 /** 127 * Show the form 128 * 129 * @param array $err Error messages. Each item is an error message. 130 * It may either be a string message name or array message name and 131 * parameters, like the second argument to OutputPage::wrapWikiMsg(). 132 */ 133 function showForm( $err ) { 134 global $wgContLang; 135 136 $this->getSkin()->setRelevantTitle( $this->oldTitle ); 137 138 $oldTitleLink = Linker::link( $this->oldTitle ); 139 140 $out = $this->getOutput(); 141 $out->setPageTitle( $this->msg( 'move-page', $this->oldTitle->getPrefixedText() ) ); 142 $out->addModules( 'mediawiki.special.movePage' ); 143 144 $newTitle = $this->newTitle; 145 146 if ( !$newTitle ) { 147 # Show the current title as a default 148 # when the form is first opened. 149 $newTitle = $this->oldTitle; 150 } elseif ( !count( $err ) ) { 151 # If a title was supplied, probably from the move log revert 152 # link, check for validity. We can then show some diagnostic 153 # information and save a click. 154 $newerr = $this->oldTitle->isValidMoveOperation( $newTitle ); 155 if ( is_array( $newerr ) ) { 156 $err = $newerr; 157 } 158 } 159 160 $user = $this->getUser(); 161 162 if ( count( $err ) == 1 && isset( $err[0][0] ) && $err[0][0] == 'articleexists' 163 && $newTitle->quickUserCan( 'delete', $user ) 164 ) { 165 $out->addWikiMsg( 'delete_and_move_text', $newTitle->getPrefixedText() ); 166 $movepagebtn = $this->msg( 'delete_and_move' )->text(); 167 $submitVar = 'wpDeleteAndMove'; 168 $confirm = " 169 <tr> 170 <td></td> 171 <td class='mw-input'>" . 172 Xml::checkLabel( 173 $this->msg( 'delete_and_move_confirm' )->text(), 174 'wpConfirm', 175 'wpConfirm' 176 ) . 177 "</td> 178 </tr>"; 179 $err = array(); 180 } else { 181 if ( $this->oldTitle->getNamespace() == NS_USER && !$this->oldTitle->isSubpage() ) { 182 $out->wrapWikiMsg( 183 "<div class=\"error mw-moveuserpage-warning\">\n$1\n</div>", 184 'moveuserpage-warning' 185 ); 186 } elseif ( $this->oldTitle->getNamespace() == NS_CATEGORY ) { 187 $out->wrapWikiMsg( 188 "<div class=\"error mw-movecategorypage-warning\">\n$1\n</div>", 189 'movecategorypage-warning' 190 ); 191 } 192 193 $out->addWikiMsg( $this->getConfig()->get( 'FixDoubleRedirects' ) ? 194 'movepagetext' : 195 'movepagetext-noredirectfixer' 196 ); 197 $movepagebtn = $this->msg( 'movepagebtn' )->text(); 198 $submitVar = 'wpMove'; 199 $confirm = false; 200 } 201 202 if ( count( $err ) == 1 && isset( $err[0][0] ) && $err[0][0] == 'file-exists-sharedrepo' 203 && $user->isAllowed( 'reupload-shared' ) 204 ) { 205 $out->addWikiMsg( 'move-over-sharedrepo', $newTitle->getPrefixedText() ); 206 $submitVar = 'wpMoveOverSharedFile'; 207 $err = array(); 208 } 209 210 $oldTalk = $this->oldTitle->getTalkPage(); 211 $oldTitleSubpages = $this->oldTitle->hasSubpages(); 212 $oldTitleTalkSubpages = $this->oldTitle->getTalkPage()->hasSubpages(); 213 214 $canMoveSubpage = ( $oldTitleSubpages || $oldTitleTalkSubpages ) && 215 !count( $this->oldTitle->getUserPermissionsErrors( 'move-subpages', $user ) ); 216 217 # We also want to be able to move assoc. subpage talk-pages even if base page 218 # has no associated talk page, so || with $oldTitleTalkSubpages. 219 $considerTalk = !$this->oldTitle->isTalkPage() && 220 ( $oldTalk->exists() 221 || ( $oldTitleTalkSubpages && $canMoveSubpage ) ); 222 223 $dbr = wfGetDB( DB_SLAVE ); 224 if ( $this->getConfig()->get( 'FixDoubleRedirects' ) ) { 225 $hasRedirects = $dbr->selectField( 'redirect', '1', 226 array( 227 'rd_namespace' => $this->oldTitle->getNamespace(), 228 'rd_title' => $this->oldTitle->getDBkey(), 229 ), __METHOD__ ); 230 } else { 231 $hasRedirects = false; 232 } 233 234 if ( $considerTalk ) { 235 $out->addWikiMsg( 'movepagetalktext' ); 236 } 237 238 if ( count( $err ) ) { 239 $out->addHTML( "<div class='error'>\n" ); 240 $action_desc = $this->msg( 'action-move' )->plain(); 241 $out->addWikiMsg( 'permissionserrorstext-withaction', count( $err ), $action_desc ); 242 243 if ( count( $err ) == 1 ) { 244 $errMsg = $err[0]; 245 $errMsgName = array_shift( $errMsg ); 246 247 if ( $errMsgName == 'hookaborted' ) { 248 $out->addHTML( "<p>{$errMsg[0]}</p>\n" ); 249 } else { 250 $out->addWikiMsgArray( $errMsgName, $errMsg ); 251 } 252 } else { 253 $errStr = array(); 254 255 foreach ( $err as $errMsg ) { 256 if ( $errMsg[0] == 'hookaborted' ) { 257 $errStr[] = $errMsg[1]; 258 } else { 259 $errMsgName = array_shift( $errMsg ); 260 $errStr[] = $this->msg( $errMsgName, $errMsg )->parse(); 261 } 262 } 263 264 $out->addHTML( '<ul><li>' . implode( "</li>\n<li>", $errStr ) . "</li></ul>\n" ); 265 } 266 $out->addHTML( "</div>\n" ); 267 } 268 269 if ( $this->oldTitle->isProtected( 'move' ) ) { 270 # Is the title semi-protected? 271 if ( $this->oldTitle->isSemiProtected( 'move' ) ) { 272 $noticeMsg = 'semiprotectedpagemovewarning'; 273 $classes[] = 'mw-textarea-sprotected'; 274 } else { 275 # Then it must be protected based on static groups (regular) 276 $noticeMsg = 'protectedpagemovewarning'; 277 $classes[] = 'mw-textarea-protected'; 278 } 279 $out->addHTML( "<div class='mw-warning-with-logexcerpt'>\n" ); 280 $out->addWikiMsg( $noticeMsg ); 281 LogEventsList::showLogExtract( 282 $out, 283 'protect', 284 $this->oldTitle, 285 '', 286 array( 'lim' => 1 ) 287 ); 288 $out->addHTML( "</div>\n" ); 289 } 290 291 // Byte limit (not string length limit) for wpReason and wpNewTitleMain 292 // is enforced in the mediawiki.special.movePage module 293 294 $immovableNamespaces = array(); 295 296 foreach ( array_keys( $this->getLanguage()->getNamespaces() ) as $nsId ) { 297 if ( !MWNamespace::isMovable( $nsId ) ) { 298 $immovableNamespaces[] = $nsId; 299 } 300 } 301 302 $handler = ContentHandler::getForTitle( $this->oldTitle ); 303 304 $out->addHTML( 305 Xml::openElement( 306 'form', 307 array( 308 'method' => 'post', 309 'action' => $this->getPageTitle()->getLocalURL( 'action=submit' ), 310 'id' => 'movepage' 311 ) 312 ) . 313 Xml::openElement( 'fieldset' ) . 314 Xml::element( 'legend', null, $this->msg( 'move-page-legend' )->text() ) . 315 Xml::openElement( 'table', array( 'id' => 'mw-movepage-table' ) ) . 316 "<tr> 317 <td class='mw-label'>" . 318 $this->msg( 'movearticle' )->escaped() . 319 "</td> 320 <td class='mw-input'> 321 <strong>{$oldTitleLink}</strong> 322 </td> 323 </tr> 324 <tr> 325 <td class='mw-label'>" . 326 Xml::label( $this->msg( 'newtitle' )->text(), 'wpNewTitleMain' ) . 327 "</td> 328 <td class='mw-input'>" . 329 Html::namespaceSelector( 330 array( 331 'selected' => $newTitle->getNamespace(), 332 'exclude' => $immovableNamespaces 333 ), 334 array( 'name' => 'wpNewTitleNs', 'id' => 'wpNewTitleNs' ) 335 ) . 336 Xml::input( 337 'wpNewTitleMain', 338 60, 339 $wgContLang->recodeForEdit( $newTitle->getText() ), 340 array( 341 'type' => 'text', 342 'id' => 'wpNewTitleMain', 343 'maxlength' => 255 344 ) 345 ) . 346 Html::hidden( 'wpOldTitle', $this->oldTitle->getPrefixedText() ) . 347 "</td> 348 </tr> 349 <tr> 350 <td class='mw-label'>" . 351 Xml::label( $this->msg( 'movereason' )->text(), 'wpReason' ) . 352 "</td> 353 <td class='mw-input'>" . 354 Xml::input( 'wpReason', 60, $this->reason, array( 355 'type' => 'text', 356 'id' => 'wpReason', 357 'maxlength' => 200, 358 ) ) . 359 "</td> 360 </tr>" 361 ); 362 363 if ( $considerTalk ) { 364 $out->addHTML( " 365 <tr> 366 <td></td> 367 <td class='mw-input'>" . 368 Xml::checkLabel( 369 $this->msg( 'movetalk' )->text(), 370 'wpMovetalk', 371 'wpMovetalk', 372 $this->moveTalk 373 ) . 374 "</td> 375 </tr>" 376 ); 377 } 378 379 if ( $user->isAllowed( 'suppressredirect' ) ) { 380 if ( $handler->supportsRedirects() ) { 381 $isChecked = $this->leaveRedirect; 382 $options = array(); 383 } else { 384 $isChecked = false; 385 $options = array( 386 'disabled' => 'disabled' 387 ); 388 } 389 $out->addHTML( " 390 <tr> 391 <td></td> 392 <td class='mw-input' >" . 393 Xml::checkLabel( 394 $this->msg( 'move-leave-redirect' )->text(), 395 'wpLeaveRedirect', 396 'wpLeaveRedirect', 397 $isChecked, 398 $options 399 ) . 400 "</td> 401 </tr>" 402 ); 403 } 404 405 if ( $hasRedirects ) { 406 $out->addHTML( " 407 <tr> 408 <td></td> 409 <td class='mw-input' >" . 410 Xml::checkLabel( 411 $this->msg( 'fix-double-redirects' )->text(), 412 'wpFixRedirects', 413 'wpFixRedirects', 414 $this->fixRedirects 415 ) . 416 "</td> 417 </tr>" 418 ); 419 } 420 421 if ( $canMoveSubpage ) { 422 $maximumMovedPages = $this->getConfig()->get( 'MaximumMovedPages' ); 423 $out->addHTML( " 424 <tr> 425 <td></td> 426 <td class=\"mw-input\">" . 427 Xml::check( 428 'wpMovesubpages', 429 # Don't check the box if we only have talk subpages to 430 # move and we aren't moving the talk page. 431 $this->moveSubpages && ( $this->oldTitle->hasSubpages() || $this->moveTalk ), 432 array( 'id' => 'wpMovesubpages' ) 433 ) . ' ' . 434 Xml::tags( 'label', array( 'for' => 'wpMovesubpages' ), 435 $this->msg( 436 ( $this->oldTitle->hasSubpages() 437 ? 'move-subpages' 438 : 'move-talk-subpages' ) 439 )->numParams( $maximumMovedPages )->params( $maximumMovedPages )->parse() 440 ) . 441 "</td> 442 </tr>" 443 ); 444 } 445 446 $watchChecked = $user->isLoggedIn() && ( $this->watch || $user->getBoolOption( 'watchmoves' ) 447 || $user->isWatched( $this->oldTitle ) ); 448 # Don't allow watching if user is not logged in 449 if ( $user->isLoggedIn() ) { 450 $out->addHTML( " 451 <tr> 452 <td></td> 453 <td class='mw-input'>" . 454 Xml::checkLabel( 455 $this->msg( 'move-watch' )->text(), 456 'wpWatch', 457 'watch', 458 $watchChecked 459 ) . 460 "</td> 461 </tr>" ); 462 } 463 464 $out->addHTML( " 465 {$confirm} 466 <tr> 467 <td> </td> 468 <td class='mw-submit'>" . 469 Xml::submitButton( $movepagebtn, array( 'name' => $submitVar ) ) . 470 "</td> 471 </tr>" . 472 Xml::closeElement( 'table' ) . 473 Html::hidden( 'wpEditToken', $user->getEditToken() ) . 474 Xml::closeElement( 'fieldset' ) . 475 Xml::closeElement( 'form' ) . 476 "\n" 477 ); 478 479 $this->showLogFragment( $this->oldTitle ); 480 $this->showSubpages( $this->oldTitle ); 481 } 482 483 function doSubmit() { 484 $user = $this->getUser(); 485 486 if ( $user->pingLimiter( 'move' ) ) { 487 throw new ThrottledError; 488 } 489 490 $ot = $this->oldTitle; 491 $nt = $this->newTitle; 492 493 # don't allow moving to pages with # in 494 if ( !$nt || $nt->hasFragment() ) { 495 $this->showForm( array( array( 'badtitletext' ) ) ); 496 497 return; 498 } 499 500 # Show a warning if the target file exists on a shared repo 501 if ( $nt->getNamespace() == NS_FILE 502 && !( $this->moveOverShared && $user->isAllowed( 'reupload-shared' ) ) 503 && !RepoGroup::singleton()->getLocalRepo()->findFile( $nt ) 504 && wfFindFile( $nt ) 505 ) { 506 $this->showForm( array( array( 'file-exists-sharedrepo' ) ) ); 507 508 return; 509 } 510 511 # Delete to make way if requested 512 if ( $this->deleteAndMove ) { 513 $permErrors = $nt->getUserPermissionsErrors( 'delete', $user ); 514 if ( count( $permErrors ) ) { 515 # Only show the first error 516 $this->showForm( $permErrors ); 517 518 return; 519 } 520 521 $reason = $this->msg( 'delete_and_move_reason', $ot )->inContentLanguage()->text(); 522 523 // Delete an associated image if there is 524 if ( $nt->getNamespace() == NS_FILE ) { 525 $file = wfLocalFile( $nt ); 526 if ( $file->exists() ) { 527 $file->delete( $reason, false ); 528 } 529 } 530 531 $error = ''; // passed by ref 532 $page = WikiPage::factory( $nt ); 533 $deleteStatus = $page->doDeleteArticleReal( $reason, false, 0, true, $error, $user ); 534 if ( !$deleteStatus->isGood() ) { 535 $this->showForm( $deleteStatus->getErrorsArray() ); 536 537 return; 538 } 539 } 540 541 $handler = ContentHandler::getForTitle( $ot ); 542 543 if ( !$handler->supportsRedirects() ) { 544 $createRedirect = false; 545 } elseif ( $user->isAllowed( 'suppressredirect' ) ) { 546 $createRedirect = $this->leaveRedirect; 547 } else { 548 $createRedirect = true; 549 } 550 551 # Do the actual move. 552 $error = $ot->moveTo( $nt, true, $this->reason, $createRedirect ); 553 if ( $error !== true ) { 554 $this->showForm( $error ); 555 556 return; 557 } 558 559 if ( $this->getConfig()->get( 'FixDoubleRedirects' ) && $this->fixRedirects ) { 560 DoubleRedirectJob::fixRedirects( 'move', $ot, $nt ); 561 } 562 563 $out = $this->getOutput(); 564 $out->setPageTitle( $this->msg( 'pagemovedsub' ) ); 565 566 $oldLink = Linker::link( 567 $ot, 568 null, 569 array( 'id' => 'movepage-oldlink' ), 570 array( 'redirect' => 'no' ) 571 ); 572 $newLink = Linker::linkKnown( 573 $nt, 574 null, 575 array( 'id' => 'movepage-newlink' ) 576 ); 577 $oldText = $ot->getPrefixedText(); 578 $newText = $nt->getPrefixedText(); 579 580 if ( $ot->exists() ) { 581 //NOTE: we assume that if the old title exists, it's because it was re-created as 582 // a redirect to the new title. This is not safe, but what we did before was 583 // even worse: we just determined whether a redirect should have been created, 584 // and reported that it was created if it should have, without any checks. 585 // Also note that isRedirect() is unreliable because of bug 37209. 586 $msgName = 'movepage-moved-redirect'; 587 } else { 588 $msgName = 'movepage-moved-noredirect'; 589 } 590 591 $out->addHTML( $this->msg( 'movepage-moved' )->rawParams( $oldLink, 592 $newLink )->params( $oldText, $newText )->parseAsBlock() ); 593 $out->addWikiMsg( $msgName ); 594 595 wfRunHooks( 'SpecialMovepageAfterMove', array( &$this, &$ot, &$nt ) ); 596 597 # Now we move extra pages we've been asked to move: subpages and talk 598 # pages. First, if the old page or the new page is a talk page, we 599 # can't move any talk pages: cancel that. 600 if ( $ot->isTalkPage() || $nt->isTalkPage() ) { 601 $this->moveTalk = false; 602 } 603 604 if ( count( $ot->getUserPermissionsErrors( 'move-subpages', $user ) ) ) { 605 $this->moveSubpages = false; 606 } 607 608 # Next make a list of id's. This might be marginally less efficient 609 # than a more direct method, but this is not a highly performance-cri- 610 # tical code path and readable code is more important here. 611 # 612 # Note: this query works nicely on MySQL 5, but the optimizer in MySQL 613 # 4 might get confused. If so, consider rewriting as a UNION. 614 # 615 # If the target namespace doesn't allow subpages, moving with subpages 616 # would mean that you couldn't move them back in one operation, which 617 # is bad. 618 # @todo FIXME: A specific error message should be given in this case. 619 620 // @todo FIXME: Use Title::moveSubpages() here 621 $dbr = wfGetDB( DB_MASTER ); 622 if ( $this->moveSubpages && ( 623 MWNamespace::hasSubpages( $nt->getNamespace() ) || ( 624 $this->moveTalk 625 && MWNamespace::hasSubpages( $nt->getTalkPage()->getNamespace() ) 626 ) 627 ) ) { 628 $conds = array( 629 'page_title' . $dbr->buildLike( $ot->getDBkey() . '/', $dbr->anyString() ) 630 . ' OR page_title = ' . $dbr->addQuotes( $ot->getDBkey() ) 631 ); 632 $conds['page_namespace'] = array(); 633 if ( MWNamespace::hasSubpages( $nt->getNamespace() ) ) { 634 $conds['page_namespace'][] = $ot->getNamespace(); 635 } 636 if ( $this->moveTalk && 637 MWNamespace::hasSubpages( $nt->getTalkPage()->getNamespace() ) 638 ) { 639 $conds['page_namespace'][] = $ot->getTalkPage()->getNamespace(); 640 } 641 } elseif ( $this->moveTalk ) { 642 $conds = array( 643 'page_namespace' => $ot->getTalkPage()->getNamespace(), 644 'page_title' => $ot->getDBkey() 645 ); 646 } else { 647 # Skip the query 648 $conds = null; 649 } 650 651 $extraPages = array(); 652 if ( !is_null( $conds ) ) { 653 $extraPages = TitleArray::newFromResult( 654 $dbr->select( 'page', 655 array( 'page_id', 'page_namespace', 'page_title' ), 656 $conds, 657 __METHOD__ 658 ) 659 ); 660 } 661 662 $extraOutput = array(); 663 $count = 1; 664 foreach ( $extraPages as $oldSubpage ) { 665 if ( $ot->equals( $oldSubpage ) || $nt->equals( $oldSubpage ) ) { 666 # Already did this one. 667 continue; 668 } 669 670 $newPageName = preg_replace( 671 '#^' . preg_quote( $ot->getDBkey(), '#' ) . '#', 672 StringUtils::escapeRegexReplacement( $nt->getDBkey() ), # bug 21234 673 $oldSubpage->getDBkey() 674 ); 675 676 if ( $oldSubpage->isTalkPage() ) { 677 $newNs = $nt->getTalkPage()->getNamespace(); 678 } else { 679 $newNs = $nt->getSubjectPage()->getNamespace(); 680 } 681 682 # Bug 14385: we need makeTitleSafe because the new page names may 683 # be longer than 255 characters. 684 $newSubpage = Title::makeTitleSafe( $newNs, $newPageName ); 685 if ( !$newSubpage ) { 686 $oldLink = Linker::linkKnown( $oldSubpage ); 687 $extraOutput[] = $this->msg( 'movepage-page-unmoved' )->rawParams( $oldLink ) 688 ->params( Title::makeName( $newNs, $newPageName ) )->escaped(); 689 continue; 690 } 691 692 # This was copy-pasted from Renameuser, bleh. 693 if ( $newSubpage->exists() && !$oldSubpage->isValidMoveTarget( $newSubpage ) ) { 694 $link = Linker::linkKnown( $newSubpage ); 695 $extraOutput[] = $this->msg( 'movepage-page-exists' )->rawParams( $link )->escaped(); 696 } else { 697 $success = $oldSubpage->moveTo( $newSubpage, true, $this->reason, $createRedirect ); 698 699 if ( $success === true ) { 700 if ( $this->fixRedirects ) { 701 DoubleRedirectJob::fixRedirects( 'move', $oldSubpage, $newSubpage ); 702 } 703 $oldLink = Linker::link( 704 $oldSubpage, 705 null, 706 array(), 707 array( 'redirect' => 'no' ) 708 ); 709 710 $newLink = Linker::linkKnown( $newSubpage ); 711 $extraOutput[] = $this->msg( 'movepage-page-moved' ) 712 ->rawParams( $oldLink, $newLink )->escaped(); 713 ++$count; 714 715 $maximumMovedPages = $this->getConfig()->get( 'MaximumMovedPages' ); 716 if ( $count >= $maximumMovedPages ) { 717 $extraOutput[] = $this->msg( 'movepage-max-pages' ) 718 ->numParams( $maximumMovedPages )->escaped(); 719 break; 720 } 721 } else { 722 $oldLink = Linker::linkKnown( $oldSubpage ); 723 $newLink = Linker::link( $newSubpage ); 724 $extraOutput[] = $this->msg( 'movepage-page-unmoved' ) 725 ->rawParams( $oldLink, $newLink )->escaped(); 726 } 727 } 728 } 729 730 if ( $extraOutput !== array() ) { 731 $out->addHTML( "<ul>\n<li>" . implode( "</li>\n<li>", $extraOutput ) . "</li>\n</ul>" ); 732 } 733 734 # Deal with watches (we don't watch subpages) 735 WatchAction::doWatchOrUnwatch( $this->watch, $ot, $user ); 736 WatchAction::doWatchOrUnwatch( $this->watch, $nt, $user ); 737 } 738 739 function showLogFragment( $title ) { 740 $moveLogPage = new LogPage( 'move' ); 741 $out = $this->getOutput(); 742 $out->addHTML( Xml::element( 'h2', null, $moveLogPage->getName()->text() ) ); 743 LogEventsList::showLogExtract( $out, 'move', $title ); 744 } 745 746 function showSubpages( $title ) { 747 if ( !MWNamespace::hasSubpages( $title->getNamespace() ) ) { 748 return; 749 } 750 751 $subpages = $title->getSubpages(); 752 $count = $subpages instanceof TitleArray ? $subpages->count() : 0; 753 754 $out = $this->getOutput(); 755 $out->wrapWikiMsg( '== $1 ==', array( 'movesubpage', $count ) ); 756 757 # No subpages. 758 if ( $count == 0 ) { 759 $out->addWikiMsg( 'movenosubpage' ); 760 761 return; 762 } 763 764 $out->addWikiMsg( 'movesubpagetext', $this->getLanguage()->formatNum( $count ) ); 765 $out->addHTML( "<ul>\n" ); 766 767 foreach ( $subpages as $subpage ) { 768 $link = Linker::link( $subpage ); 769 $out->addHTML( "<li>$link</li>\n" ); 770 } 771 $out->addHTML( "</ul>\n" ); 772 } 773 774 protected function getGroupName() { 775 return 'pagetools'; 776 } 777 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |