[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/specials/ -> SpecialMovepage.php (source)

   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                      ) . '&#160;' .
 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>&#160;</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  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1