MediaWiki  REL1_21
SpecialMovepage.php
Go to the documentation of this file.
00001 <?php
00029 class MovePageForm extends UnlistedSpecialPage {
00030 
00034         var $oldTitle, $newTitle; # Objects
00035         var $reason; # Text input
00036         var $moveTalk, $deleteAndMove, $moveSubpages, $fixRedirects, $leaveRedirect, $moveOverShared; # Checks
00037 
00038         private $watch = false;
00039 
00040         public function __construct() {
00041                 parent::__construct( 'Movepage' );
00042         }
00043 
00044         public function execute( $par ) {
00045                 $this->checkReadOnly();
00046 
00047                 $this->setHeaders();
00048                 $this->outputHeader();
00049 
00050                 $request = $this->getRequest();
00051                 $target = !is_null( $par ) ? $par : $request->getVal( 'target' );
00052 
00053                 // Yes, the use of getVal() and getText() is wanted, see bug 20365
00054 
00055                 $oldTitleText = $request->getVal( 'wpOldTitle', $target );
00056                 $this->oldTitle = Title::newFromText( $oldTitleText );
00057 
00058                 if( is_null( $this->oldTitle ) ) {
00059                         throw new ErrorPageError( 'notargettitle', 'notargettext' );
00060                 }
00061                 if( !$this->oldTitle->exists() ) {
00062                         throw new ErrorPageError( 'nopagetitle', 'nopagetext' );
00063                 }
00064 
00065                 $newTitleTextMain = $request->getText( 'wpNewTitleMain' );
00066                 $newTitleTextNs = $request->getInt( 'wpNewTitleNs', $this->oldTitle->getNamespace() );
00067                 // Backwards compatibility for forms submitting here from other sources
00068                 // which is more common than it should be..
00069                 $newTitleText_bc = $request->getText( 'wpNewTitle' );
00070                 $this->newTitle = strlen( $newTitleText_bc ) > 0
00071                         ? Title::newFromText( $newTitleText_bc )
00072                         : Title::makeTitleSafe( $newTitleTextNs, $newTitleTextMain );
00073 
00074                 $user = $this->getUser();
00075 
00076                 # Check rights
00077                 $permErrors = $this->oldTitle->getUserPermissionsErrors( 'move', $user );
00078                 if ( count( $permErrors ) ) {
00079                         // Auto-block user's IP if the account was "hard" blocked
00080                         $user->spreadAnyEditBlock();
00081                         throw new PermissionsError( 'move', $permErrors );
00082                 }
00083 
00084                 $def = !$request->wasPosted();
00085 
00086                 $this->reason = $request->getText( 'wpReason' );
00087                 $this->moveTalk = $request->getBool( 'wpMovetalk', $def );
00088                 $this->fixRedirects = $request->getBool( 'wpFixRedirects', $def );
00089                 $this->leaveRedirect = $request->getBool( 'wpLeaveRedirect', $def );
00090                 $this->moveSubpages = $request->getBool( 'wpMovesubpages', false );
00091                 $this->deleteAndMove = $request->getBool( 'wpDeleteAndMove' ) && $request->getBool( 'wpConfirm' );
00092                 $this->moveOverShared = $request->getBool( 'wpMoveOverSharedFile', false );
00093                 $this->watch = $request->getCheck( 'wpWatch' ) && $user->isLoggedIn();
00094 
00095                 if ( 'submit' == $request->getVal( 'action' ) && $request->wasPosted()
00096                         && $user->matchEditToken( $request->getVal( 'wpEditToken' ) ) ) {
00097                         $this->doSubmit();
00098                 } else {
00099                         $this->showForm( array() );
00100                 }
00101         }
00102 
00110         function showForm( $err ) {
00111                 global $wgContLang, $wgFixDoubleRedirects, $wgMaximumMovedPages;
00112 
00113                 $this->getSkin()->setRelevantTitle( $this->oldTitle );
00114 
00115                 $oldTitleLink = Linker::link( $this->oldTitle );
00116 
00117                 $out = $this->getOutput();
00118                 $out->setPageTitle( $this->msg( 'move-page', $this->oldTitle->getPrefixedText() ) );
00119                 $out->addModules( 'mediawiki.special.movePage' );
00120 
00121                 $newTitle = $this->newTitle;
00122 
00123                 if ( !$newTitle ) {
00124                         # Show the current title as a default
00125                         # when the form is first opened.
00126                         $newTitle = $this->oldTitle;
00127                 } elseif ( !count( $err ) ) {
00128                         # If a title was supplied, probably from the move log revert
00129                         # link, check for validity. We can then show some diagnostic
00130                         # information and save a click.
00131                         $newerr = $this->oldTitle->isValidMoveOperation( $newTitle );
00132                         if( is_array( $newerr ) ) {
00133                                 $err = $newerr;
00134                         }
00135                 }
00136 
00137                 $user = $this->getUser();
00138 
00139                 if ( count( $err ) == 1 && isset( $err[0][0] ) && $err[0][0] == 'articleexists'
00140                         && $newTitle->quickUserCan( 'delete', $user )
00141                 ) {
00142                         $out->addWikiMsg( 'delete_and_move_text', $newTitle->getPrefixedText() );
00143                         $movepagebtn = $this->msg( 'delete_and_move' )->text();
00144                         $submitVar = 'wpDeleteAndMove';
00145                         $confirm = "
00146                                 <tr>
00147                                         <td></td>
00148                                         <td class='mw-input'>" .
00149                                                 Xml::checkLabel( $this->msg( 'delete_and_move_confirm' )->text(), 'wpConfirm', 'wpConfirm' ) .
00150                                         "</td>
00151                                 </tr>";
00152                         $err = array();
00153                 } else {
00154                         if ( $this->oldTitle->getNamespace() == NS_USER && !$this->oldTitle->isSubpage() ) {
00155                                 $out->wrapWikiMsg( "<div class=\"error mw-moveuserpage-warning\">\n$1\n</div>", 'moveuserpage-warning' );
00156                         }
00157                         $out->addWikiMsg( $wgFixDoubleRedirects ? 'movepagetext' :
00158                                 'movepagetext-noredirectfixer' );
00159                         $movepagebtn = $this->msg( 'movepagebtn' )->text();
00160                         $submitVar = 'wpMove';
00161                         $confirm = false;
00162                 }
00163 
00164                 if ( count( $err ) == 1 && isset( $err[0][0] ) && $err[0][0] == 'file-exists-sharedrepo'
00165                         && $user->isAllowed( 'reupload-shared' )
00166                 ) {
00167                         $out->addWikiMsg( 'move-over-sharedrepo', $newTitle->getPrefixedText() );
00168                         $submitVar = 'wpMoveOverSharedFile';
00169                         $err = array();
00170                 }
00171 
00172                 $oldTalk = $this->oldTitle->getTalkPage();
00173                 $oldTitleSubpages = $this->oldTitle->hasSubpages();
00174                 $oldTitleTalkSubpages = $this->oldTitle->getTalkPage()->hasSubpages();
00175 
00176                 $canMoveSubpage = ( $oldTitleSubpages || $oldTitleTalkSubpages ) &&
00177                         !count( $this->oldTitle->getUserPermissionsErrors( 'move-subpages', $user ) );
00178 
00179                 # We also want to be able to move assoc. subpage talk-pages even if base page
00180                 # has no associated talk page, so || with $oldTitleTalkSubpages.
00181                 $considerTalk = !$this->oldTitle->isTalkPage() &&
00182                         ( $oldTalk->exists()
00183                                 || ( $oldTitleTalkSubpages && $canMoveSubpage ) );
00184 
00185                 $dbr = wfGetDB( DB_SLAVE );
00186                 if ( $wgFixDoubleRedirects ) {
00187                         $hasRedirects = $dbr->selectField( 'redirect', '1',
00188                                 array(
00189                                         'rd_namespace' => $this->oldTitle->getNamespace(),
00190                                         'rd_title' => $this->oldTitle->getDBkey(),
00191                                 ), __METHOD__ );
00192                 } else {
00193                         $hasRedirects = false;
00194                 }
00195 
00196                 if ( $considerTalk ) {
00197                         $out->addWikiMsg( 'movepagetalktext' );
00198                 }
00199 
00200                 if ( count( $err ) ) {
00201                         $out->addHTML( "<div class='error'>\n" );
00202                         $action_desc = $this->msg( 'action-move' )->plain();
00203                         $out->addWikiMsg( 'permissionserrorstext-withaction', count( $err ), $action_desc );
00204 
00205                         if ( count( $err ) == 1 ) {
00206                                 $errMsg = $err[0];
00207                                 $errMsgName = array_shift( $errMsg );
00208                                 if ( $errMsgName == 'hookaborted' ) {
00209                                         $out->addHTML( "<p>{$errMsg[0]}</p>\n" );
00210                                 } else {
00211                                         $out->addWikiMsgArray( $errMsgName, $errMsg );
00212                                 }
00213                         } else {
00214                                 $errStr = array();
00215                                 foreach( $err as $errMsg ) {
00216                                         if( $errMsg[0] == 'hookaborted' ) {
00217                                                 $errStr[] = $errMsg[1];
00218                                         } else {
00219                                                 $errMsgName = array_shift( $errMsg );
00220                                                 $errStr[] = $this->msg( $errMsgName, $errMsg )->parse();
00221                                         }
00222                                 }
00223 
00224                                 $out->addHTML( '<ul><li>' . implode( "</li>\n<li>", $errStr ) . "</li></ul>\n" );
00225                         }
00226                         $out->addHTML( "</div>\n" );
00227                 }
00228 
00229                 if ( $this->oldTitle->isProtected( 'move' ) ) {
00230                         # Is the title semi-protected?
00231                         if ( $this->oldTitle->isSemiProtected( 'move' ) ) {
00232                                 $noticeMsg = 'semiprotectedpagemovewarning';
00233                                 $classes[] = 'mw-textarea-sprotected';
00234                         } else {
00235                                 # Then it must be protected based on static groups (regular)
00236                                 $noticeMsg = 'protectedpagemovewarning';
00237                                 $classes[] = 'mw-textarea-protected';
00238                         }
00239                         $out->addHTML( "<div class='mw-warning-with-logexcerpt'>\n" );
00240                         $out->addWikiMsg( $noticeMsg );
00241                         LogEventsList::showLogExtract( $out, 'protect', $this->oldTitle, '', array( 'lim' => 1 ) );
00242                         $out->addHTML( "</div>\n" );
00243                 }
00244 
00245                 // Byte limit (not string length limit) for wpReason and wpNewTitleMain
00246                 // is enforced in the mediawiki.special.movePage module
00247 
00248                 $immovableNamespaces = array();
00249 
00250                 foreach ( array_keys( $this->getLanguage()->getNamespaces() ) as $nsId ) {
00251                         if ( !MWNamespace::isMovable( $nsId ) ) {
00252                                 $immovableNamespaces[] = $nsId;
00253                         }
00254                 }
00255 
00256                 $handler = ContentHandler::getForTitle( $this->oldTitle );
00257 
00258                 $out->addHTML(
00259                         Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalURL( 'action=submit' ), 'id' => 'movepage' ) ) .
00260                         Xml::openElement( 'fieldset' ) .
00261                         Xml::element( 'legend', null, $this->msg( 'move-page-legend' )->text() ) .
00262                         Xml::openElement( 'table', array( 'id' => 'mw-movepage-table' ) ) .
00263                         "<tr>
00264                                 <td class='mw-label'>" .
00265                                         $this->msg( 'movearticle' )->escaped() .
00266                                 "</td>
00267                                 <td class='mw-input'>
00268                                         <strong>{$oldTitleLink}</strong>
00269                                 </td>
00270                         </tr>
00271                         <tr>
00272                                 <td class='mw-label'>" .
00273                                         Xml::label( $this->msg( 'newtitle' )->text(), 'wpNewTitleMain' ) .
00274                                 "</td>
00275                                 <td class='mw-input'>" .
00276                                         Html::namespaceSelector(
00277                                                 array(
00278                                                         'selected' => $newTitle->getNamespace(),
00279                                                         'exclude' => $immovableNamespaces
00280                                                 ),
00281                                                 array( 'name' => 'wpNewTitleNs', 'id' => 'wpNewTitleNs' )
00282                                         ) .
00283                                         Xml::input( 'wpNewTitleMain', 60, $wgContLang->recodeForEdit( $newTitle->getText() ), array(
00284                                                 'type' => 'text',
00285                                                 'id' => 'wpNewTitleMain',
00286                                                 'maxlength' => 255,
00287                                         ) ) .
00288                                         Html::hidden( 'wpOldTitle', $this->oldTitle->getPrefixedText() ) .
00289                                 "</td>
00290                         </tr>
00291                         <tr>
00292                                 <td class='mw-label'>" .
00293                                         Xml::label( $this->msg( 'movereason' )->text(), 'wpReason' ) .
00294                                 "</td>
00295                                 <td class='mw-input'>" .
00296                                         Html::element( 'textarea', array( 'name' => 'wpReason', 'id' => 'wpReason', 'cols' => 60, 'rows' => 2,
00297                                         'maxlength' => 200 ), $this->reason ) .
00298                                 "</td>
00299                         </tr>"
00300                 );
00301 
00302                 if( $considerTalk ) {
00303                         $out->addHTML( "
00304                                 <tr>
00305                                         <td></td>
00306                                         <td class='mw-input'>" .
00307                                                 Xml::checkLabel( $this->msg( 'movetalk' )->text(), 'wpMovetalk', 'wpMovetalk', $this->moveTalk ) .
00308                                         "</td>
00309                                 </tr>"
00310                         );
00311                 }
00312 
00313                 if ( $user->isAllowed( 'suppressredirect' ) && $handler->supportsRedirects() ) {
00314                         $out->addHTML( "
00315                                 <tr>
00316                                         <td></td>
00317                                         <td class='mw-input' >" .
00318                                                 Xml::checkLabel( $this->msg( 'move-leave-redirect' )->text(), 'wpLeaveRedirect',
00319                                                         'wpLeaveRedirect', $this->leaveRedirect ) .
00320                                         "</td>
00321                                 </tr>"
00322                         );
00323                 }
00324 
00325                 if ( $hasRedirects ) {
00326                         $out->addHTML( "
00327                                 <tr>
00328                                         <td></td>
00329                                         <td class='mw-input' >" .
00330                                                 Xml::checkLabel( $this->msg( 'fix-double-redirects' )->text(), 'wpFixRedirects',
00331                                                         'wpFixRedirects', $this->fixRedirects ) .
00332                                         "</td>
00333                                 </tr>"
00334                         );
00335                 }
00336 
00337                 if( $canMoveSubpage ) {
00338                         $out->addHTML( "
00339                                 <tr>
00340                                         <td></td>
00341                                         <td class=\"mw-input\">" .
00342                                 Xml::check(
00343                                         'wpMovesubpages',
00344                                         # Don't check the box if we only have talk subpages to
00345                                         # move and we aren't moving the talk page.
00346                                         $this->moveSubpages && ( $this->oldTitle->hasSubpages() || $this->moveTalk ),
00347                                         array( 'id' => 'wpMovesubpages' )
00348                                 ) . '&#160;' .
00349                                 Xml::tags( 'label', array( 'for' => 'wpMovesubpages' ),
00350                                         $this->msg(
00351                                                 ( $this->oldTitle->hasSubpages()
00352                                                         ? 'move-subpages'
00353                                                         : 'move-talk-subpages' )
00354                                                 )->numParams( $wgMaximumMovedPages )->params( $wgMaximumMovedPages )->parse()
00355                                 ) .
00356                                         "</td>
00357                                 </tr>"
00358                         );
00359                 }
00360 
00361                 $watchChecked = $user->isLoggedIn() && ( $this->watch || $user->getBoolOption( 'watchmoves' )
00362                         || $user->isWatched( $this->oldTitle ) );
00363                 # Don't allow watching if user is not logged in
00364                 if( $user->isLoggedIn() ) {
00365                         $out->addHTML( "
00366                         <tr>
00367                                 <td></td>
00368                                 <td class='mw-input'>" .
00369                                         Xml::checkLabel( $this->msg( 'move-watch' )->text(), 'wpWatch', 'watch', $watchChecked ) .
00370                                 "</td>
00371                         </tr>");
00372                 }
00373 
00374                 $out->addHTML( "
00375                                 {$confirm}
00376                         <tr>
00377                                 <td>&#160;</td>
00378                                 <td class='mw-submit'>" .
00379                                         Xml::submitButton( $movepagebtn, array( 'name' => $submitVar ) ) .
00380                                 "</td>
00381                         </tr>" .
00382                         Xml::closeElement( 'table' ) .
00383                         Html::hidden( 'wpEditToken', $user->getEditToken() ) .
00384                         Xml::closeElement( 'fieldset' ) .
00385                         Xml::closeElement( 'form' ) .
00386                         "\n"
00387                 );
00388 
00389                 $this->showLogFragment( $this->oldTitle );
00390                 $this->showSubpages( $this->oldTitle );
00391 
00392         }
00393 
00394         function doSubmit() {
00395                 global $wgMaximumMovedPages, $wgFixDoubleRedirects;
00396 
00397                 $user = $this->getUser();
00398 
00399                 if ( $user->pingLimiter( 'move' ) ) {
00400                         throw new ThrottledError;
00401                 }
00402 
00403                 $ot = $this->oldTitle;
00404                 $nt = $this->newTitle;
00405 
00406                 # don't allow moving to pages with # in
00407                 if ( !$nt || $nt->getFragment() != '' ) {
00408                         $this->showForm( array( array( 'badtitletext' ) ) );
00409                         return;
00410                 }
00411 
00412                 # Show a warning if the target file exists on a shared repo
00413                 if ( $nt->getNamespace() == NS_FILE
00414                         && !( $this->moveOverShared && $user->isAllowed( 'reupload-shared' ) )
00415                         && !RepoGroup::singleton()->getLocalRepo()->findFile( $nt )
00416                         && wfFindFile( $nt ) )
00417                 {
00418                         $this->showForm( array( array( 'file-exists-sharedrepo' ) ) );
00419                         return;
00420 
00421                 }
00422 
00423                 # Delete to make way if requested
00424                 if ( $this->deleteAndMove ) {
00425                         $permErrors = $nt->getUserPermissionsErrors( 'delete', $user );
00426                         if ( count( $permErrors ) ) {
00427                                 # Only show the first error
00428                                 $this->showForm( $permErrors );
00429                                 return;
00430                         }
00431 
00432                         $reason = $this->msg( 'delete_and_move_reason', $ot )->inContentLanguage()->text();
00433 
00434                         // Delete an associated image if there is
00435                         if ( $nt->getNamespace() == NS_FILE ) {
00436                                 $file = wfLocalFile( $nt );
00437                                 if ( $file->exists() ) {
00438                                         $file->delete( $reason, false );
00439                                 }
00440                         }
00441 
00442                         $error = ''; // passed by ref
00443                         $page = WikiPage::factory( $nt );
00444                         $deleteStatus = $page->doDeleteArticleReal( $reason, false, 0, true, $error, $user );
00445                         if ( !$deleteStatus->isGood() ) {
00446                                 $this->showForm( $deleteStatus->getErrorsArray() );
00447                                 return;
00448                         }
00449                 }
00450 
00451                 $handler = ContentHandler::getForTitle( $ot );
00452 
00453                 if ( !$handler->supportsRedirects() ) {
00454                         $createRedirect = false;
00455                 } elseif ( $user->isAllowed( 'suppressredirect' ) ) {
00456                         $createRedirect = $this->leaveRedirect;
00457                 } else {
00458                         $createRedirect = true;
00459                 }
00460 
00461                 # Do the actual move.
00462                 $error = $ot->moveTo( $nt, true, $this->reason, $createRedirect );
00463                 if ( $error !== true ) {
00464                         $this->showForm( $error );
00465                         return;
00466                 }
00467 
00468                 if ( $wgFixDoubleRedirects && $this->fixRedirects ) {
00469                         DoubleRedirectJob::fixRedirects( 'move', $ot, $nt );
00470                 }
00471 
00472                 $out = $this->getOutput();
00473                 $out->setPageTitle( $this->msg( 'pagemovedsub' ) );
00474 
00475                 $oldLink = Linker::link(
00476                         $ot,
00477                         null,
00478                         array(),
00479                         array( 'redirect' => 'no' )
00480                 );
00481                 $newLink = Linker::linkKnown( $nt );
00482                 $oldText = $ot->getPrefixedText();
00483                 $newText = $nt->getPrefixedText();
00484 
00485                 if ( $ot->exists() ) {
00486                         //NOTE: we assume that if the old title exists, it's because it was re-created as
00487                         // a redirect to the new title. This is not safe, but what we did before was
00488                         // even worse: we just determined whether a redirect should have been created,
00489                         // and reported that it was created if it should have, without any checks.
00490                         // Also note that isRedirect() is unreliable because of bug 37209.
00491                         $msgName = 'movepage-moved-redirect';
00492                 } else {
00493                         $msgName = 'movepage-moved-noredirect';
00494                 }
00495 
00496                 $out->addHTML( $this->msg( 'movepage-moved' )->rawParams( $oldLink,
00497                         $newLink )->params( $oldText, $newText )->parseAsBlock() );
00498                 $out->addWikiMsg( $msgName );
00499 
00500                 wfRunHooks( 'SpecialMovepageAfterMove', array( &$this, &$ot, &$nt ) );
00501 
00502                 # Now we move extra pages we've been asked to move: subpages and talk
00503                 # pages.  First, if the old page or the new page is a talk page, we
00504                 # can't move any talk pages: cancel that.
00505                 if( $ot->isTalkPage() || $nt->isTalkPage() ) {
00506                         $this->moveTalk = false;
00507                 }
00508 
00509                 if ( count( $ot->getUserPermissionsErrors( 'move-subpages', $user ) ) ) {
00510                         $this->moveSubpages = false;
00511                 }
00512 
00513                 # Next make a list of id's.  This might be marginally less efficient
00514                 # than a more direct method, but this is not a highly performance-cri-
00515                 # tical code path and readable code is more important here.
00516                 #
00517                 # Note: this query works nicely on MySQL 5, but the optimizer in MySQL
00518                 # 4 might get confused.  If so, consider rewriting as a UNION.
00519                 #
00520                 # If the target namespace doesn't allow subpages, moving with subpages
00521                 # would mean that you couldn't move them back in one operation, which
00522                 # is bad.
00523                 # @todo FIXME: A specific error message should be given in this case.
00524 
00525                 // @todo FIXME: Use Title::moveSubpages() here
00526                 $dbr = wfGetDB( DB_MASTER );
00527                 if( $this->moveSubpages && (
00528                         MWNamespace::hasSubpages( $nt->getNamespace() ) || (
00529                                 $this->moveTalk &&
00530                                 MWNamespace::hasSubpages( $nt->getTalkPage()->getNamespace() )
00531                         )
00532                 ) ) {
00533                         $conds = array(
00534                                 'page_title' . $dbr->buildLike( $ot->getDBkey() . '/', $dbr->anyString() )
00535                                         .' OR page_title = ' . $dbr->addQuotes( $ot->getDBkey() )
00536                         );
00537                         $conds['page_namespace'] = array();
00538                         if( MWNamespace::hasSubpages( $nt->getNamespace() ) ) {
00539                                 $conds['page_namespace'][] = $ot->getNamespace();
00540                         }
00541                         if( $this->moveTalk && MWNamespace::hasSubpages( $nt->getTalkPage()->getNamespace() ) ) {
00542                                 $conds['page_namespace'][] = $ot->getTalkPage()->getNamespace();
00543                         }
00544                 } elseif( $this->moveTalk ) {
00545                         $conds = array(
00546                                 'page_namespace' => $ot->getTalkPage()->getNamespace(),
00547                                 'page_title' => $ot->getDBkey()
00548                         );
00549                 } else {
00550                         # Skip the query
00551                         $conds = null;
00552                 }
00553 
00554                 $extraPages = array();
00555                 if( !is_null( $conds ) ) {
00556                         $extraPages = TitleArray::newFromResult(
00557                                 $dbr->select( 'page',
00558                                         array( 'page_id', 'page_namespace', 'page_title' ),
00559                                         $conds,
00560                                         __METHOD__
00561                                 )
00562                         );
00563                 }
00564 
00565                 $extraOutput = array();
00566                 $count = 1;
00567                 foreach( $extraPages as $oldSubpage ) {
00568                         if( $ot->equals( $oldSubpage ) ) {
00569                                 # Already did this one.
00570                                 continue;
00571                         }
00572 
00573                         $newPageName = preg_replace(
00574                                 '#^'.preg_quote( $ot->getDBkey(), '#' ).'#',
00575                                 StringUtils::escapeRegexReplacement( $nt->getDBkey() ), # bug 21234
00576                                 $oldSubpage->getDBkey()
00577                         );
00578                         if( $oldSubpage->isTalkPage() ) {
00579                                 $newNs = $nt->getTalkPage()->getNamespace();
00580                         } else {
00581                                 $newNs = $nt->getSubjectPage()->getNamespace();
00582                         }
00583                         # Bug 14385: we need makeTitleSafe because the new page names may
00584                         # be longer than 255 characters.
00585                         $newSubpage = Title::makeTitleSafe( $newNs, $newPageName );
00586                         if( !$newSubpage ) {
00587                                 $oldLink = Linker::linkKnown( $oldSubpage );
00588                                 $extraOutput[] = $this->msg( 'movepage-page-unmoved' )->rawParams( $oldLink
00589                                         )->params( Title::makeName( $newNs, $newPageName ) )->escaped();
00590                                 continue;
00591                         }
00592 
00593                         # This was copy-pasted from Renameuser, bleh.
00594                         if ( $newSubpage->exists() && !$oldSubpage->isValidMoveTarget( $newSubpage ) ) {
00595                                 $link = Linker::linkKnown( $newSubpage );
00596                                 $extraOutput[] = $this->msg( 'movepage-page-exists' )->rawParams( $link )->escaped();
00597                         } else {
00598                                 $success = $oldSubpage->moveTo( $newSubpage, true, $this->reason, $createRedirect );
00599                                 if( $success === true ) {
00600                                         if ( $this->fixRedirects ) {
00601                                                 DoubleRedirectJob::fixRedirects( 'move', $oldSubpage, $newSubpage );
00602                                         }
00603                                         $oldLink = Linker::link(
00604                                                 $oldSubpage,
00605                                                 null,
00606                                                 array(),
00607                                                 array( 'redirect' => 'no' )
00608                                         );
00609                                         $newLink = Linker::linkKnown( $newSubpage );
00610                                         $extraOutput[] = $this->msg( 'movepage-page-moved' )->rawParams( $oldLink, $newLink )->escaped();
00611                                         ++$count;
00612                                         if( $count >= $wgMaximumMovedPages ) {
00613                                                 $extraOutput[] = $this->msg( 'movepage-max-pages' )->numParams( $wgMaximumMovedPages )->escaped();
00614                                                 break;
00615                                         }
00616                                 } else {
00617                                         $oldLink = Linker::linkKnown( $oldSubpage );
00618                                         $newLink = Linker::link( $newSubpage );
00619                                         $extraOutput[] = $this->msg( 'movepage-page-unmoved' )->rawParams( $oldLink, $newLink )->escaped();
00620                                 }
00621                         }
00622 
00623                 }
00624 
00625                 if( $extraOutput !== array() ) {
00626                         $out->addHTML( "<ul>\n<li>" . implode( "</li>\n<li>", $extraOutput ) . "</li>\n</ul>" );
00627                 }
00628 
00629                 # Deal with watches (we don't watch subpages)
00630                 if( $this->watch && $user->isLoggedIn() ) {
00631                         $user->addWatch( $ot );
00632                         $user->addWatch( $nt );
00633                 } else {
00634                         $user->removeWatch( $ot );
00635                         $user->removeWatch( $nt );
00636                 }
00637 
00638                 # Re-clear the file redirect cache, which may have been polluted by
00639                 # parsing in messages above. See CR r56745.
00640                 # @todo FIXME: Needs a more robust solution inside FileRepo.
00641                 if( $ot->getNamespace() == NS_FILE ) {
00642                         RepoGroup::singleton()->getLocalRepo()->invalidateImageRedirect( $ot );
00643                 }
00644         }
00645 
00646         function showLogFragment( $title ) {
00647                 $moveLogPage = new LogPage( 'move' );
00648                 $out = $this->getOutput();
00649                 $out->addHTML( Xml::element( 'h2', null, $moveLogPage->getName()->text() ) );
00650                 LogEventsList::showLogExtract( $out, 'move', $title );
00651         }
00652 
00653         function showSubpages( $title ) {
00654                 if( !MWNamespace::hasSubpages( $title->getNamespace() ) )
00655                         return;
00656 
00657                 $subpages = $title->getSubpages();
00658                 $count = $subpages instanceof TitleArray ? $subpages->count() : 0;
00659 
00660                 $out = $this->getOutput();
00661                 $out->wrapWikiMsg( '== $1 ==', array( 'movesubpage', $count ) );
00662 
00663                 # No subpages.
00664                 if ( $count == 0 ) {
00665                         $out->addWikiMsg( 'movenosubpage' );
00666                         return;
00667                 }
00668 
00669                 $out->addWikiMsg( 'movesubpagetext', $this->getLanguage()->formatNum( $count ) );
00670                 $out->addHTML( "<ul>\n" );
00671 
00672                 foreach( $subpages as $subpage ) {
00673                         $link = Linker::link( $subpage );
00674                         $out->addHTML( "<li>$link</li>\n" );
00675                 }
00676                 $out->addHTML( "</ul>\n" );
00677         }
00678 
00679         protected function getGroupName() {
00680                 return 'pagetools';
00681         }
00682 }