Index: trunk/phase3/includes/Article.php |
— | — | @@ -37,19 +37,6 @@ |
38 | 38 | /**@}}*/ |
39 | 39 | |
40 | 40 | /** |
41 | | - * Constants used by internal components to get rollback results |
42 | | - */ |
43 | | - const SUCCESS = 0; // Operation successful |
44 | | - const PERM_DENIED = 1; // Permission denied |
45 | | - const BLOCKED = 2; // User has been blocked |
46 | | - const READONLY = 3; // Wiki is in read-only mode |
47 | | - const BAD_TOKEN = 4; // Invalid token specified |
48 | | - const BAD_TITLE = 5; // $this is not a valid Article |
49 | | - const ALREADY_ROLLED = 6; // Someone else already rolled this back. $from and $summary will be set |
50 | | - const ONLY_AUTHOR = 7; // User is the only author of the page |
51 | | - const RATE_LIMITED = 8; |
52 | | - |
53 | | - /** |
54 | 41 | * Constructor and clear the article |
55 | 42 | * @param $title Reference to a Title object. |
56 | 43 | * @param $oldId Integer revision ID, null to fetch from request, zero for current |
— | — | @@ -2273,57 +2260,73 @@ |
2274 | 2261 | /** |
2275 | 2262 | * Roll back the most recent consecutive set of edits to a page |
2276 | 2263 | * from the same user; fails if there are no eligible edits to |
2277 | | - * roll back to, e.g. user is the sole contributor |
| 2264 | + * roll back to, e.g. user is the sole contributor. This function |
| 2265 | + * performs permissions checks on $wgUser, then calls commitRollback() |
| 2266 | + * to do the dirty work |
2278 | 2267 | * |
2279 | 2268 | * @param string $fromP - Name of the user whose edits to rollback. |
2280 | 2269 | * @param string $summary - Custom summary. Set to default summary if empty. |
2281 | 2270 | * @param string $token - Rollback token. |
2282 | 2271 | * @param bool $bot - If true, mark all reverted edits as bot. |
2283 | 2272 | * |
2284 | | - * @param array $resultDetails contains result-specific dict of additional values |
2285 | | - * ALREADY_ROLLED : 'current' (rev) |
2286 | | - * SUCCESS : 'summary' (str), 'current' (rev), 'target' (rev) |
| 2273 | + * @param array $resultDetails contains result-specific array of additional values |
| 2274 | + * 'alreadyrolled' : 'current' (rev) |
| 2275 | + * success : 'summary' (str), 'current' (rev), 'target' (rev) |
2287 | 2276 | * |
2288 | | - * @return self::SUCCESS on succes, self::* on failure |
| 2277 | + * @return array of errors, each error formatted as array(messagekey, param1, param2, ...). |
| 2278 | + * On success, the array is empty. This array can also be passed to OutputPage::showPermissionsErrorPage(). |
| 2279 | + * NOTE: If the user is blocked, 'blocked' is passed as a message, but it doesn't exist. Be sure to check |
| 2280 | + * it before calling showPermissionsErrorPage(). The same is true for 'actionthrottledtext', which |
| 2281 | + * is passed if the rate limit is passed. |
2289 | 2282 | */ |
2290 | 2283 | public function doRollback( $fromP, $summary, $token, $bot, &$resultDetails ) { |
2291 | | - global $wgUser, $wgUseRCPatrol; |
| 2284 | + global $wgUser; |
2292 | 2285 | $resultDetails = null; |
2293 | 2286 | |
2294 | | - # Just in case it's being called from elsewhere |
2295 | | - |
2296 | | - if( $wgUser->isAllowed( 'rollback' ) && $this->mTitle->userCan( 'edit' ) ) { |
2297 | | - if( $wgUser->isBlocked() ) { |
2298 | | - return self::BLOCKED; |
2299 | | - } |
2300 | | - } else { |
2301 | | - return self::PERM_DENIED; |
2302 | | - } |
2303 | | - |
2304 | | - if ( wfReadOnly() ) { |
2305 | | - return self::READONLY; |
2306 | | - } |
2307 | | - |
| 2287 | + # Check permissions |
| 2288 | + $errors = array_merge( $this->mTitle->getUserPermissionsErrors( 'edit', $wgUser ), |
| 2289 | + $this->mTitle->getUserPermissionsErrors( 'rollback', $wgUser ) ); |
2308 | 2290 | if( !$wgUser->matchEditToken( $token, array( $this->mTitle->getPrefixedText(), $fromP ) ) ) |
2309 | | - return self::BAD_TOKEN; |
| 2291 | + $errors[] = array( 'sessionfailure' ); |
2310 | 2292 | |
2311 | 2293 | if ( $wgUser->pingLimiter('rollback') || $wgUser->pingLimiter() ) { |
2312 | | - return self::RATE_LIMITED; |
| 2294 | + $errors[] = array( 'actionthrottledtext' ); |
2313 | 2295 | } |
| 2296 | + if ( $wgUser->isBlocked() ) |
| 2297 | + $errors[] = array( 'blocked' ); |
2314 | 2298 | |
| 2299 | + # If there were errors, bail out now |
| 2300 | + if(!empty($errors)) |
| 2301 | + return $errors; |
| 2302 | + |
| 2303 | + return $this->commitRollback($fromP, $summary, $bot, $resultDetails); |
| 2304 | + } |
| 2305 | + |
| 2306 | + /** |
| 2307 | + * Backend implementation of doRollback(), please refer there for parameter and return value documentation |
| 2308 | + * |
| 2309 | + * NOTE: This function does NOT check ANY permissions, it just commits the rollback to the DB. |
| 2310 | + * Therefore, you should only call this function directly if you really know what you're doing. If you don't, use doRollback() instead |
| 2311 | + */ |
| 2312 | + public function commitRollback($fromP, $summary, $bot, &$resultDetails) { |
| 2313 | + global $wgUseRCPatrol; |
2315 | 2314 | $dbw = wfGetDB( DB_MASTER ); |
2316 | 2315 | |
2317 | 2316 | # Get the last editor |
2318 | 2317 | $current = Revision::newFromTitle( $this->mTitle ); |
2319 | 2318 | if( is_null( $current ) ) { |
2320 | 2319 | # Something wrong... no page? |
2321 | | - return self::BAD_TITLE; |
| 2320 | + return array(array('notanarticle')); |
2322 | 2321 | } |
2323 | 2322 | |
2324 | 2323 | $from = str_replace( '_', ' ', $fromP ); |
2325 | 2324 | if( $from != $current->getUserText() ) { |
2326 | 2325 | $resultDetails = array( 'current' => $current ); |
2327 | | - return self::ALREADY_ROLLED; |
| 2326 | + return array(array('alreadyrolled', |
| 2327 | + htmlspecialchars($this->mTitle->getPrefixedText()), |
| 2328 | + htmlspecialchars($fromP), |
| 2329 | + htmlspecialchars($current->getUserText()) |
| 2330 | + )); |
2328 | 2331 | } |
2329 | 2332 | |
2330 | 2333 | # Get the last edit not by this guy |
— | — | @@ -2331,17 +2334,15 @@ |
2332 | 2335 | $user_text = $dbw->addQuotes( $current->getUserText() ); |
2333 | 2336 | $s = $dbw->selectRow( 'revision', |
2334 | 2337 | array( 'rev_id', 'rev_timestamp' ), |
2335 | | - array( |
2336 | | - 'rev_page' => $current->getPage(), |
| 2338 | + array( 'rev_page' => $current->getPage(), |
2337 | 2339 | "rev_user <> {$user} OR rev_user_text <> {$user_text}" |
2338 | 2340 | ), __METHOD__, |
2339 | | - array( |
2340 | | - 'USE INDEX' => 'page_timestamp', |
| 2341 | + array( 'USE INDEX' => 'page_timestamp', |
2341 | 2342 | 'ORDER BY' => 'rev_timestamp DESC' ) |
2342 | 2343 | ); |
2343 | 2344 | if( $s === false ) { |
2344 | | - # Something wrong |
2345 | | - return self::ONLY_AUTHOR; |
| 2345 | + # No one else ever edited this page |
| 2346 | + return array(array('cantrollback')); |
2346 | 2347 | } |
2347 | 2348 | |
2348 | 2349 | $set = array(); |
— | — | @@ -2364,7 +2365,7 @@ |
2365 | 2366 | ); |
2366 | 2367 | } |
2367 | 2368 | |
2368 | | - # Get the edit summary |
| 2369 | + # Generate the edit summary if necessary |
2369 | 2370 | $target = Revision::newFromId( $s->rev_id ); |
2370 | 2371 | if( empty( $summary ) ) |
2371 | 2372 | { |
— | — | @@ -2393,7 +2394,7 @@ |
2394 | 2395 | 'current' => $current, |
2395 | 2396 | 'target' => $target, |
2396 | 2397 | ); |
2397 | | - return self::SUCCESS; |
| 2398 | + return array(); |
2398 | 2399 | } |
2399 | 2400 | |
2400 | 2401 | /** |
— | — | @@ -2401,19 +2402,8 @@ |
2402 | 2403 | */ |
2403 | 2404 | function rollback() { |
2404 | 2405 | global $wgUser, $wgOut, $wgRequest, $wgUseRCPatrol; |
2405 | | - |
2406 | 2406 | $details = null; |
2407 | 2407 | |
2408 | | - # Skip the permissions-checking in doRollback() itself, by checking permissions here. |
2409 | | - |
2410 | | - $perm_errors = array_merge( $this->mTitle->getUserPermissionsErrors( 'edit', $wgUser ), |
2411 | | - $this->mTitle->getUserPermissionsErrors( 'rollback', $wgUser ) ); |
2412 | | - |
2413 | | - if (count($perm_errors)) { |
2414 | | - $wgOut->showPermissionsErrorPage( $perm_errors ); |
2415 | | - return; |
2416 | | - } |
2417 | | - |
2418 | 2408 | $result = $this->doRollback( |
2419 | 2409 | $wgRequest->getVal( 'from' ), |
2420 | 2410 | $wgRequest->getText( 'summary' ), |
— | — | @@ -2421,62 +2411,30 @@ |
2422 | 2412 | $wgRequest->getBool( 'bot' ), |
2423 | 2413 | $details |
2424 | 2414 | ); |
2425 | | - |
2426 | | - switch( $result ) { |
2427 | | - case self::BLOCKED: |
2428 | | - $wgOut->blockedPage(); |
2429 | | - break; |
2430 | | - case self::PERM_DENIED: |
2431 | | - $wgOut->permissionRequired( 'rollback' ); |
2432 | | - break; |
2433 | | - case self::READONLY: |
2434 | | - $wgOut->readOnlyPage( $this->getContent() ); |
2435 | | - break; |
2436 | | - case self::BAD_TOKEN: |
2437 | | - $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) ); |
2438 | | - $wgOut->addWikiText( wfMsg( 'sessionfailure' ) ); |
2439 | | - break; |
2440 | | - case self::BAD_TITLE: |
2441 | | - $wgOut->addHtml( wfMsg( 'notanarticle' ) ); |
2442 | | - break; |
2443 | | - case self::ALREADY_ROLLED: |
2444 | | - $current = $details['current']; |
2445 | | - $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) ); |
2446 | | - $wgOut->addWikiText( |
2447 | | - wfMsg( 'alreadyrolled', |
2448 | | - htmlspecialchars( $this->mTitle->getPrefixedText() ), |
2449 | | - htmlspecialchars( $wgRequest->getVal( 'from' ) ), |
2450 | | - htmlspecialchars( $current->getUserText() ) |
2451 | | - ) |
2452 | | - ); |
2453 | | - if( $current->getComment() != '' ) { |
2454 | | - $wgOut->addHtml( wfMsg( 'editcomment', |
2455 | | - $wgUser->getSkin()->formatComment( $current->getComment() ) ) ); |
2456 | | - } |
2457 | | - break; |
2458 | | - case self::ONLY_AUTHOR: |
2459 | | - $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) ); |
2460 | | - $wgOut->addHtml( wfMsg( 'cantrollback' ) ); |
2461 | | - break; |
2462 | | - case self::RATE_LIMITED: |
2463 | | - $wgOut->rateLimited(); |
2464 | | - break; |
2465 | | - case self::SUCCESS: |
2466 | | - $current = $details['current']; |
2467 | | - $target = $details['target']; |
2468 | | - $wgOut->setPageTitle( wfMsg( 'actioncomplete' ) ); |
2469 | | - $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
2470 | | - $old = $wgUser->getSkin()->userLink( $current->getUser(), $current->getUserText() ) |
2471 | | - . $wgUser->getSkin()->userToolLinks( $current->getUser(), $current->getUserText() ); |
2472 | | - $new = $wgUser->getSkin()->userLink( $target->getUser(), $target->getUserText() ) |
2473 | | - . $wgUser->getSkin()->userToolLinks( $target->getUser(), $target->getUserText() ); |
2474 | | - $wgOut->addHtml( wfMsgExt( 'rollback-success', array( 'parse', 'replaceafter' ), $old, $new ) ); |
2475 | | - $wgOut->returnToMain( false, $this->mTitle ); |
2476 | | - break; |
2477 | | - default: |
2478 | | - throw new MWException( __METHOD__ . ": Unknown return value `{$result}`" ); |
| 2415 | + |
| 2416 | + if(in_array(array('blocked'), $result)) { |
| 2417 | + $wgOut->blockedPage(); |
| 2418 | + return; |
2479 | 2419 | } |
| 2420 | + if(in_array(array('actionthrottledtext'), $result)) { |
| 2421 | + $wgOut->rateLimited(); |
| 2422 | + return; |
| 2423 | + } |
| 2424 | + if(!empty($result)) { |
| 2425 | + $wgOut->showPermissionsErrorPage( $result ); |
| 2426 | + return; |
| 2427 | + } |
2480 | 2428 | |
| 2429 | + $current = $details['current']; |
| 2430 | + $target = $details['target']; |
| 2431 | + $wgOut->setPageTitle( wfMsg( 'actioncomplete' ) ); |
| 2432 | + $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
| 2433 | + $old = $wgUser->getSkin()->userLink( $current->getUser(), $current->getUserText() ) |
| 2434 | + . $wgUser->getSkin()->userToolLinks( $current->getUser(), $current->getUserText() ); |
| 2435 | + $new = $wgUser->getSkin()->userLink( $target->getUser(), $target->getUserText() ) |
| 2436 | + . $wgUser->getSkin()->userToolLinks( $target->getUser(), $target->getUserText() ); |
| 2437 | + $wgOut->addHtml( wfMsgExt( 'rollback-success', array( 'parse', 'replaceafter' ), $old, $new ) ); |
| 2438 | + $wgOut->returnToMain( false, $this->mTitle ); |
2481 | 2439 | } |
2482 | 2440 | |
2483 | 2441 | |