var $mUserText; //!<
/**@}}*/
+ /**
+ * Constants used by internal components to get rollback results
+ */
+ const SUCCESS = 0; // Operation successful
+ const PERM_DENIED = 1; // Permission denied
+ const BLOCKED = 2; // User has been blocked
+ const READONLY = 3; // Wiki is in read-only mode
+ const BAD_TOKEN = 4; // Invalid token specified
+ const BAD_TITLE = 5; // $this is not a valid Article
+ const ALREADY_ROLLED = 6; // Someone else already rolled this back. $from and $summary will be set
+ const ONLY_AUTHOR = 7; // User is the only author of the page
+
/**
* Constructor and clear the article
* @param $title Reference to a Title object.
}
# Should the parser cache be used?
- $pcache = $wgEnableParserCache &&
- intval( $wgUser->getOption( 'stubthreshold' ) ) == 0 &&
- $this->exists() &&
- empty( $oldid );
+ $pcache = $wgEnableParserCache
+ && intval( $wgUser->getOption( 'stubthreshold' ) ) == 0
+ && $this->exists()
+ && empty( $oldid )
+ && !$this->mTitle->isCssOrJsPage()
+ && !$this->mTitle->isCssJsSubpage();
wfDebug( 'Article::view using parser cache: ' . ($pcache ? 'yes' : 'no' ) . "\n" );
if ( $wgUser->getOption( 'stubthreshold' ) ) {
wfIncrStats( 'pcache_miss_stub' );
}
if( !$outputDone ) {
$wgOut->setRevisionId( $this->getRevIdFetched() );
- // Wrap site/user css/js in pre and don't parse. User pages need
- // to be subpages, site pages just need to end in ".css" or ".js".
-
- // @todo: use $this->mTitle->isCssJsSubpage() when php is fixed/
- // a workaround is found.
- if (
- ($ns == NS_USER and preg_match('#/\w+\.(css|js)$#',$this->mTitle->getDBkey(),$matches))
- or ($ns == NS_MEDIAWIKI and preg_match('/.(css|js)$/', $this->mTitle->getDBkey(), $matches))
- ) {
- $wgOut->addWikiText( wfMsg('clearyourcache'));
- $wgOut->addHTML(
- "<pre class=\"mw-code mw-{$matches[1]}\" dir=\"ltr\">"
- .htmlspecialchars($this->mContent)."\n</pre>"
- );
- } else if ( $rt = Title::newFromRedirect( $text ) ) {
+
+ // Pages containing custom CSS or JavaScript get special treatment
+ if( $this->mTitle->isCssOrJsPage() || $this->mTitle->isCssJsSubpage() ) {
+ $wgOut->addHtml( wfMsgExt( 'clearyourcache', 'parse' ) );
+
+ // Give hooks a chance to customise the output
+ if( wfRunHooks( 'ShowRawCssJs', array( $this->mContent, $this->mTitle, $wgOut ) ) ) {
+ // Wrap the whole lot in a <pre> and don't parse
+ preg_match( '!\.(css|js)$!u', $this->mTitle->getText(), $m );
+ $wgOut->addHtml( "<pre class=\"mw-code mw-{$m[1]}\" dir=\"ltr\">\n" );
+ $wgOut->addHtml( htmlspecialchars( $this->mContent ) );
+ $wgOut->addHtml( "\n</pre>\n" );
+ }
+
+ }
+
+ elseif ( $rt = Title::newFromRedirect( $text ) ) {
# Display redirect
$imageDir = $wgContLang->isRTL() ? 'rtl' : 'ltr';
$imageUrl = $wgStylePath.'/common/images/redirect' . $imageDir . '.png';
}
/**
- * Revert a modification
- */
- function rollback() {
- global $wgUser, $wgOut, $wgRequest, $wgUseRCPatrol;
-
+ * Roll back the most recent consecutive set of edits to a page
+ * from the same user; fails if there are no eligible edits to
+ * roll back to, e.g. user is the sole contributor
+ *
+ * @param string $fromP - Name of the user whose edits to rollback.
+ * @param string $summary - Custom summary. Set to default summary if empty.
+ * @param string $token - Rollback token.
+ * @param bool $bot - If true, mark all reverted edits as bot.
+ *
+ * @param array $resultDetails contains result-specific dict of additional values
+ * ALREADY_ROLLED : 'current' (rev)
+ * SUCCESS : 'summary' (str), 'current' (rev), 'target' (rev)
+ *
+ * @return self::SUCCESS on succes, self::* on failure
+ */
+ public function doRollback( $fromP, $summary, $token, $bot, &$resultDetails ) {
+ global $wgUser, $wgUseRCPatrol;
+ $resultDetails = null;
+
if( $wgUser->isAllowed( 'rollback' ) ) {
if( $wgUser->isBlocked() ) {
- $wgOut->blockedPage();
- return;
+ return self::BLOCKED;
}
} else {
- $wgOut->permissionRequired( 'rollback' );
- return;
+ return self::PERM_DENIED;
}
-
+
if ( wfReadOnly() ) {
- $wgOut->readOnlyPage( $this->getContent() );
- return;
+ return self::READONLY;
}
- if( !$wgUser->matchEditToken( $wgRequest->getVal( 'token' ),
- array( $this->mTitle->getPrefixedText(),
- $wgRequest->getVal( 'from' ) ) ) ) {
- $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) );
- $wgOut->addWikiText( wfMsg( 'sessionfailure' ) );
- return;
- }
- $dbw = wfGetDB( DB_MASTER );
+ if( !$wgUser->matchEditToken( $token, array( $this->mTitle->getPrefixedText(), $fromP ) ) )
+ return self::BAD_TOKEN;
- # Enhanced rollback, marks edits rc_bot=1
- $bot = $wgRequest->getBool( 'bot' );
-
- # Replace all this user's current edits with the next one down
+ $dbw = wfGetDB( DB_MASTER );
# Get the last editor
$current = Revision::newFromTitle( $this->mTitle );
if( is_null( $current ) ) {
# Something wrong... no page?
- $wgOut->addHTML( wfMsg( 'notanarticle' ) );
- return;
+ return self::BAD_TITLE;
}
- $from = str_replace( '_', ' ', $wgRequest->getVal( 'from' ) );
+ $from = str_replace( '_', ' ', $fromP );
if( $from != $current->getUserText() ) {
- $wgOut->setPageTitle( wfMsg('rollbackfailed') );
- $wgOut->addWikiText( wfMsg( 'alreadyrolled',
- htmlspecialchars( $this->mTitle->getPrefixedText()),
- htmlspecialchars( $from ),
- htmlspecialchars( $current->getUserText() ) ) );
- if( $current->getComment() != '') {
- $wgOut->addHTML(
- wfMsg( 'editcomment',
- $wgUser->getSkin()->formatComment( $current->getComment() ) ) );
- }
- return;
+ $resultDetails = array( 'current' => $current );
+ return self::ALREADY_ROLLED;
}
# Get the last edit not by this guy
);
if( $s === false ) {
# Something wrong
- $wgOut->setPageTitle(wfMsg('rollbackfailed'));
- $wgOut->addHTML( wfMsg( 'cantrollback' ) );
- return;
+ return self::ONLY_AUTHOR;
}
-
+
$set = array();
if ( $bot ) {
# Mark all reverted edits as bot
if ( $set ) {
$dbw->update( 'recentchanges', $set,
- array( /* WHERE */
- 'rc_cur_id' => $current->getPage(),
- 'rc_user_text' => $current->getUserText(),
- "rc_timestamp > '{$s->rev_timestamp}'",
- ), __METHOD__
- );
+ array( /* WHERE */
+ 'rc_cur_id' => $current->getPage(),
+ 'rc_user_text' => $current->getUserText(),
+ "rc_timestamp > '{$s->rev_timestamp}'",
+ ), __METHOD__
+ );
}
# Get the edit summary
$target = Revision::newFromId( $s->rev_id );
- $newComment = wfMsgForContent( 'revertpage', $target->getUserText(), $from );
- $newComment = $wgRequest->getText( 'summary', $newComment );
+ if( empty( $summary ) )
+ $summary = wfMsgForContent( 'revertpage', $target->getUserText(), $from );
+
+ # Save
+ $flags = EDIT_UPDATE | EDIT_MINOR;
+ if( $bot )
+ $flags |= EDIT_FORCE_BOT;
+ $this->doEdit( $target->getText(), $summary, $flags );
+
+ $resultDetails = array(
+ 'summary' => $summary,
+ 'current' => $current,
+ 'target' => $target,
+ );
+ return self::SUCCESS;
+ }
- # Save it!
- $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
- $wgOut->setRobotpolicy( 'noindex,nofollow' );
- $wgOut->addHTML( '<h2>' . htmlspecialchars( $newComment ) . "</h2>\n<hr />\n" );
+ /**
+ * User interface for rollback operations
+ */
+ function rollback() {
+ global $wgUser, $wgOut, $wgRequest, $wgUseRCPatrol;
- $this->updateArticle( $target->getText(), $newComment, 1, $this->mTitle->userIsWatching(), $bot );
+ $details = null;
+ $result = $this->doRollback(
+ $wgRequest->getVal( 'from' ),
+ $wgRequest->getText( 'summary' ),
+ $wgRequest->getVal( 'token' ),
+ $wgRequest->getBool( 'bot' ),
+ $details
+ );
+
+ switch( $result ) {
+ case self::BLOCKED:
+ $wgOut->blockedPage();
+ break;
+ case self::PERM_DENIED:
+ $wgOut->permissionRequired( 'rollback' );
+ break;
+ case self::READONLY:
+ $wgOut->readOnlyPage( $this->getContent() );
+ break;
+ case self::BAD_TOKEN:
+ $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) );
+ $wgOut->addWikiText( wfMsg( 'sessionfailure' ) );
+ break;
+ case self::BAD_TITLE:
+ $wgOut->addHtml( wfMsg( 'notanarticle' ) );
+ break;
+ case self::ALREADY_ROLLED:
+ $current = $details['current'];
+ $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) );
+ $wgOut->addWikiText(
+ wfMsg( 'alreadyrolled',
+ htmlspecialchars( $this->mTitle->getPrefixedText() ),
+ htmlspecialchars( $wgRequest->getVal( 'from' ) ),
+ htmlspecialchars( $current->getUserText() )
+ )
+ );
+ if( $current->getComment() != '' ) {
+ $wgOut->addHtml( wfMsg( 'editcomment',
+ $wgUser->getSkin()->formatComment( $current->getComment() ) ) );
+ }
+ break;
+ case self::ONLY_AUTHOR:
+ $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) );
+ $wgOut->addHtml( wfMsg( 'cantrollback' ) );
+ break;
+ case self::SUCCESS:
+ $current = $details['current'];
+ $target = $details['target'];
+ $wgOut->setPageTitle( wfMsg( 'actioncomplete' ) );
+ $wgOut->setRobotPolicy( 'noindex,nofollow' );
+ $old = $wgUser->getSkin()->userLink( $current->getUser(), $current->getUserText() )
+ . $wgUser->getSkin()->userToolLinks( $current->getUser(), $current->getUserText() );
+ $new = $wgUser->getSkin()->userLink( $target->getUser(), $target->getUserText() )
+ . $wgUser->getSkin()->userToolLinks( $target->getUser(), $target->getUserText() );
+ $wgOut->addHtml( wfMsgExt( 'rollback-success', array( 'parse', 'replaceafter' ), $old, $new ) );
+ $wgOut->returnToMain( false, $this->mTitle );
+ break;
+ default:
+ throw new MWException( __METHOD__ . ": Unknown return value `{$retval}`" );
+ }
- $wgOut->returnToMain( false );
}
$wgOut->addParserOutput( $parserOutput );
}
-}
-
-?>
+}
\ No newline at end of file