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