MediaWiki  REL1_23
ApiMove.php
Go to the documentation of this file.
00001 <?php
00031 class ApiMove extends ApiBase {
00032 
00033     public function execute() {
00034         $user = $this->getUser();
00035         $params = $this->extractRequestParams();
00036 
00037         $this->requireOnlyOneParameter( $params, 'from', 'fromid' );
00038 
00039         if ( isset( $params['from'] ) ) {
00040             $fromTitle = Title::newFromText( $params['from'] );
00041             if ( !$fromTitle || $fromTitle->isExternal() ) {
00042                 $this->dieUsageMsg( array( 'invalidtitle', $params['from'] ) );
00043             }
00044         } elseif ( isset( $params['fromid'] ) ) {
00045             $fromTitle = Title::newFromID( $params['fromid'] );
00046             if ( !$fromTitle ) {
00047                 $this->dieUsageMsg( array( 'nosuchpageid', $params['fromid'] ) );
00048             }
00049         }
00050 
00051         if ( !$fromTitle->exists() ) {
00052             $this->dieUsageMsg( 'notanarticle' );
00053         }
00054         $fromTalk = $fromTitle->getTalkPage();
00055 
00056         $toTitle = Title::newFromText( $params['to'] );
00057         if ( !$toTitle || $toTitle->isExternal() ) {
00058             $this->dieUsageMsg( array( 'invalidtitle', $params['to'] ) );
00059         }
00060         $toTalk = $toTitle->getTalkPage();
00061 
00062         if ( $toTitle->getNamespace() == NS_FILE
00063             && !RepoGroup::singleton()->getLocalRepo()->findFile( $toTitle )
00064             && wfFindFile( $toTitle )
00065         ) {
00066             if ( !$params['ignorewarnings'] && $user->isAllowed( 'reupload-shared' ) ) {
00067                 $this->dieUsageMsg( 'sharedfile-exists' );
00068             } elseif ( !$user->isAllowed( 'reupload-shared' ) ) {
00069                 $this->dieUsageMsg( 'cantoverwrite-sharedfile' );
00070             }
00071         }
00072 
00073         // Move the page
00074         $toTitleExists = $toTitle->exists();
00075         $retval = $fromTitle->moveTo( $toTitle, true, $params['reason'], !$params['noredirect'] );
00076         if ( $retval !== true ) {
00077             $this->dieUsageMsg( reset( $retval ) );
00078         }
00079 
00080         $r = array(
00081             'from' => $fromTitle->getPrefixedText(),
00082             'to' => $toTitle->getPrefixedText(),
00083             'reason' => $params['reason']
00084         );
00085 
00086         if ( $fromTitle->exists() ) {
00087             //NOTE: we assume that if the old title exists, it's because it was re-created as
00088             // a redirect to the new title. This is not safe, but what we did before was
00089             // even worse: we just determined whether a redirect should have been created,
00090             // and reported that it was created if it should have, without any checks.
00091             // Also note that isRedirect() is unreliable because of bug 37209.
00092             $r['redirectcreated'] = '';
00093         }
00094 
00095         if ( $toTitleExists ) {
00096             $r['moveoverredirect'] = '';
00097         }
00098 
00099         // Move the talk page
00100         if ( $params['movetalk'] && $fromTalk->exists() && !$fromTitle->isTalkPage() ) {
00101             $toTalkExists = $toTalk->exists();
00102             $retval = $fromTalk->moveTo( $toTalk, true, $params['reason'], !$params['noredirect'] );
00103             if ( $retval === true ) {
00104                 $r['talkfrom'] = $fromTalk->getPrefixedText();
00105                 $r['talkto'] = $toTalk->getPrefixedText();
00106                 if ( $toTalkExists ) {
00107                     $r['talkmoveoverredirect'] = '';
00108                 }
00109             } else {
00110                 // We're not gonna dieUsage() on failure, since we already changed something
00111                 $parsed = $this->parseMsg( reset( $retval ) );
00112                 $r['talkmove-error-code'] = $parsed['code'];
00113                 $r['talkmove-error-info'] = $parsed['info'];
00114             }
00115         }
00116 
00117         $result = $this->getResult();
00118 
00119         // Move subpages
00120         if ( $params['movesubpages'] ) {
00121             $r['subpages'] = $this->moveSubpages( $fromTitle, $toTitle,
00122                 $params['reason'], $params['noredirect'] );
00123             $result->setIndexedTagName( $r['subpages'], 'subpage' );
00124 
00125             if ( $params['movetalk'] ) {
00126                 $r['subpages-talk'] = $this->moveSubpages( $fromTalk, $toTalk,
00127                     $params['reason'], $params['noredirect'] );
00128                 $result->setIndexedTagName( $r['subpages-talk'], 'subpage' );
00129             }
00130         }
00131 
00132         $watch = 'preferences';
00133         if ( isset( $params['watchlist'] ) ) {
00134             $watch = $params['watchlist'];
00135         } elseif ( $params['watch'] ) {
00136             $watch = 'watch';
00137         } elseif ( $params['unwatch'] ) {
00138             $watch = 'unwatch';
00139         }
00140 
00141         // Watch pages
00142         $this->setWatch( $watch, $fromTitle, 'watchmoves' );
00143         $this->setWatch( $watch, $toTitle, 'watchmoves' );
00144 
00145         $result->addValue( null, $this->getModuleName(), $r );
00146     }
00147 
00155     public function moveSubpages( $fromTitle, $toTitle, $reason, $noredirect ) {
00156         $retval = array();
00157         $success = $fromTitle->moveSubpages( $toTitle, true, $reason, !$noredirect );
00158         if ( isset( $success[0] ) ) {
00159             return array( 'error' => $this->parseMsg( $success ) );
00160         }
00161 
00162         // At least some pages could be moved
00163         // Report each of them separately
00164         foreach ( $success as $oldTitle => $newTitle ) {
00165             $r = array( 'from' => $oldTitle );
00166             if ( is_array( $newTitle ) ) {
00167                 $r['error'] = $this->parseMsg( reset( $newTitle ) );
00168             } else {
00169                 // Success
00170                 $r['to'] = $newTitle;
00171             }
00172             $retval[] = $r;
00173         }
00174 
00175         return $retval;
00176     }
00177 
00178     public function mustBePosted() {
00179         return true;
00180     }
00181 
00182     public function isWriteMode() {
00183         return true;
00184     }
00185 
00186     public function getAllowedParams() {
00187         return array(
00188             'from' => null,
00189             'fromid' => array(
00190                 ApiBase::PARAM_TYPE => 'integer'
00191             ),
00192             'to' => array(
00193                 ApiBase::PARAM_TYPE => 'string',
00194                 ApiBase::PARAM_REQUIRED => true
00195             ),
00196             'token' => array(
00197                 ApiBase::PARAM_TYPE => 'string',
00198                 ApiBase::PARAM_REQUIRED => true
00199             ),
00200             'reason' => '',
00201             'movetalk' => false,
00202             'movesubpages' => false,
00203             'noredirect' => false,
00204             'watch' => array(
00205                 ApiBase::PARAM_DFLT => false,
00206                 ApiBase::PARAM_DEPRECATED => true,
00207             ),
00208             'unwatch' => array(
00209                 ApiBase::PARAM_DFLT => false,
00210                 ApiBase::PARAM_DEPRECATED => true,
00211             ),
00212             'watchlist' => array(
00213                 ApiBase::PARAM_DFLT => 'preferences',
00214                 ApiBase::PARAM_TYPE => array(
00215                     'watch',
00216                     'unwatch',
00217                     'preferences',
00218                     'nochange'
00219                 ),
00220             ),
00221             'ignorewarnings' => false
00222         );
00223     }
00224 
00225     public function getParamDescription() {
00226         $p = $this->getModulePrefix();
00227 
00228         return array(
00229             'from' => "Title of the page you want to move. Cannot be used together with {$p}fromid",
00230             'fromid' => "Page ID of the page you want to move. Cannot be used together with {$p}from",
00231             'to' => 'Title you want to rename the page to',
00232             'token' => 'A move token previously retrieved through prop=info',
00233             'reason' => 'Reason for the move',
00234             'movetalk' => 'Move the talk page, if it exists',
00235             'movesubpages' => 'Move subpages, if applicable',
00236             'noredirect' => 'Don\'t create a redirect',
00237             'watch' => 'Add the page and the redirect to your watchlist',
00238             'unwatch' => 'Remove the page and the redirect from your watchlist',
00239             'watchlist' => 'Unconditionally add or remove the page from your ' .
00240                 'watchlist, use preferences or do not change watch',
00241             'ignorewarnings' => 'Ignore any warnings'
00242         );
00243     }
00244 
00245     public function getResultProperties() {
00246         return array(
00247             '' => array(
00248                 'from' => 'string',
00249                 'to' => 'string',
00250                 'reason' => 'string',
00251                 'redirectcreated' => 'boolean',
00252                 'moveoverredirect' => 'boolean',
00253                 'talkfrom' => array(
00254                     ApiBase::PROP_TYPE => 'string',
00255                     ApiBase::PROP_NULLABLE => true
00256                 ),
00257                 'talkto' => array(
00258                     ApiBase::PROP_TYPE => 'string',
00259                     ApiBase::PROP_NULLABLE => true
00260                 ),
00261                 'talkmoveoverredirect' => 'boolean',
00262                 'talkmove-error-code' => array(
00263                     ApiBase::PROP_TYPE => 'string',
00264                     ApiBase::PROP_NULLABLE => true
00265                 ),
00266                 'talkmove-error-info' => array(
00267                     ApiBase::PROP_TYPE => 'string',
00268                     ApiBase::PROP_NULLABLE => true
00269                 )
00270             )
00271         );
00272     }
00273 
00274     public function getDescription() {
00275         return 'Move a page.';
00276     }
00277 
00278     public function getPossibleErrors() {
00279         return array_merge( parent::getPossibleErrors(),
00280             $this->getRequireOnlyOneParameterErrorMessages( array( 'from', 'fromid' ) ),
00281             array(
00282                 array( 'invalidtitle', 'from' ),
00283                 array( 'nosuchpageid', 'fromid' ),
00284                 array( 'notanarticle' ),
00285                 array( 'invalidtitle', 'to' ),
00286                 array( 'sharedfile-exists' ),
00287             )
00288         );
00289     }
00290 
00291     public function needsToken() {
00292         return true;
00293     }
00294 
00295     public function getTokenSalt() {
00296         return '';
00297     }
00298 
00299     public function getExamples() {
00300         return array(
00301             'api.php?action=move&from=Badtitle&to=Goodtitle&token=123ABC&' .
00302                 'reason=Misspelled%20title&movetalk=&noredirect='
00303         );
00304     }
00305 
00306     public function getHelpUrls() {
00307         return 'https://www.mediawiki.org/wiki/API:Move';
00308     }
00309 }