r24517 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r24516‎ | r24517 | r24518 >
Date:12:00, 1 August 2007
Author:catrope
Status:old
Tags:
Comment:
apiedit: Hand-merging two files, adding one
Modified paths:
  • /branches/apiedit/phase3/includes/Article.php (modified) (history)
  • /branches/apiedit/phase3/includes/SpecialUndelete.php (modified) (history)
  • /branches/apiedit/phase3/includes/api/ApiQueryUserInfo.php (added) (history)

Diff [purge]

Index: branches/apiedit/phase3/includes/Article.php
@@ -39,15 +39,14 @@
4040 /**
4141 * Constants used by internal components to get rollback results
4242 */
43 - const SUCCESS = 0;
 43+ const SUCCESS = 0; // Operation successful
4444 const PERM_DENIED = 1; // Permission denied
45 - const BLOCKED = 2; // User has been blocked
46 - const READONLY = 3; // Wiki is in read-only mode
 45+ const BLOCKED = 2; // User has been blocked
 46+ const READONLY = 3; // Wiki is in read-only mode
4747 const BAD_TOKEN = 4; // Invalid token specified
4848 const BAD_TITLE = 5; // $this is not a valid Article
49 - const ALREADYROLLED = 6;// Someone else already rolled this back. $info['usertext'] and $info['comment'] will be set
 49+ const ALREADY_ROLLED = 6;// Someone else already rolled this back. $from and $summary will be set
5050 const ONLY_AUTHOR = 7; // User is the only author of the page
51 - const EDIT_FAILED = 8; // Article::doEdit() failed. This is a very weird error
5251
5352 /**
5453 * Constructor and clear the article
@@ -1458,19 +1457,16 @@
14591458 # Clear caches
14601459 Article::onArticleCreate( $this->mTitle );
14611460
1462 - wfRunHooks( 'ArticleInsertComplete', array( &$this, &$wgUser, $text,
1463 - $summary, $flags & EDIT_MINOR,
1464 - null, null, &$flags ) );
 1461+ wfRunHooks( 'ArticleInsertComplete', array( &$this, &$wgUser, $text, $summary,
 1462+ $flags & EDIT_MINOR, null, null, &$flags, $revision ) );
14651463 }
14661464
14671465 if ( $good && !( $flags & EDIT_DEFER_UPDATES ) ) {
14681466 wfDoUpdates();
14691467 }
14701468
1471 - wfRunHooks( 'ArticleSaveComplete',
1472 - array( &$this, &$wgUser, $text,
1473 - $summary, $flags & EDIT_MINOR,
1474 - null, null, &$flags ) );
 1469+ wfRunHooks( 'ArticleSaveComplete', array( &$this, &$wgUser, $text, $summary,
 1470+ $flags & EDIT_MINOR, null, null, &$flags, $revision ) );
14751471
14761472 wfProfileOut( __METHOD__ );
14771473 return $good;
@@ -2119,7 +2115,8 @@
21202116 'ar_text_id' => 'rev_text_id',
21212117 'ar_text' => '\'\'', // Be explicit to appease
21222118 'ar_flags' => '\'\'', // MySQL's "strict mode"...
2123 - 'ar_len' => 'rev_len'
 2119+ 'ar_len' => 'rev_len',
 2120+ 'ar_page' => $id
21242121 ), array(
21252122 'page_id' => $id,
21262123 'page_id = rev_page'
@@ -2171,17 +2168,26 @@
21722169 return true;
21732170 }
21742171
2175 - /** Backend rollback implementation. UI logic is in rollback()
 2172+ /**
 2173+ * Roll back the most recent consecutive set of edits to a page
 2174+ * from the same user; fails if there are no eligible edits to
 2175+ * roll back to, e.g. user is the sole contributor
 2176+ *
21762177 * @param string $fromP - Name of the user whose edits to rollback.
 2178+ * @param string $summary - Custom summary. Set to default summary if empty.
21772179 * @param string $token - Rollback token.
21782180 * @param bool $bot - If true, mark all reverted edits as bot.
2179 - * @param string $newComment - Custom summary. Set to default summary if empty.
2180 - * @param array $info - Reference to associative array that will be set to contain the revision ID, edit summary, etc.
 2181+ *
 2182+ * @param array $resultDetails contains result-specific dict of additional values
 2183+ * ALREADY_ROLLED : 'current' (rev)
 2184+ * SUCCESS : 'summary' (str), 'current' (rev), 'target' (rev)
 2185+ *
21812186 * @return self::SUCCESS on succes, self::* on failure
21822187 */
2183 - public function doRollback($fromP, $token, $bot = false, $newComment = "", &$info = NULL) {
 2188+ public function doRollback( $fromP, $summary, $token, $bot, &$resultDetails ) {
21842189 global $wgUser, $wgUseRCPatrol;
2185 -
 2190+ $resultDetails = null;
 2191+
21862192 if( $wgUser->isAllowed( 'rollback' ) ) {
21872193 if( $wgUser->isBlocked() ) {
21882194 return self::BLOCKED;
@@ -2189,19 +2195,15 @@
21902196 } else {
21912197 return self::PERM_DENIED;
21922198 }
2193 -
 2199+
21942200 if ( wfReadOnly() ) {
21952201 return self::READONLY;
21962202 }
2197 - if( !$wgUser->matchEditToken( $token,
2198 - array( $this->mTitle->getPrefixedText(),
2199 - $fromP ) ) ) {
 2203+ if( !$wgUser->matchEditToken( $token, array( $this->mTitle->getPrefixedText(), $fromP ) ) )
22002204 return self::BAD_TOKEN;
2201 - }
 2205+
22022206 $dbw = wfGetDB( DB_MASTER );
22032207
2204 - # Replace all this user's current edits with the next one down
2205 -
22062208 # Get the last editor
22072209 $current = Revision::newFromTitle( $this->mTitle );
22082210 if( is_null( $current ) ) {
@@ -2211,9 +2213,8 @@
22122214
22132215 $from = str_replace( '_', ' ', $fromP );
22142216 if( $from != $current->getUserText() ) {
2215 - $info['usertext'] = $current->getUserText();
2216 - $info['comment'] = $current->getComment();
2217 - return self::ALREADYROLLED;
 2217+ $resultDetails = array( 'current' => $current );
 2218+ return self::ALREADY_ROLLED;
22182219 }
22192220
22202221 # Get the last edit not by this guy
@@ -2234,7 +2235,6 @@
22352236 return self::ONLY_AUTHOR;
22362237 }
22372238
2238 - // If the reverted edits should be marked bot or patrolled, do so
22392239 $set = array();
22402240 if ( $bot ) {
22412241 # Mark all reverted edits as bot
@@ -2257,86 +2257,88 @@
22582258
22592259 # Get the edit summary
22602260 $target = Revision::newFromId( $s->rev_id );
2261 - if(empty($newComment))
2262 - $newComment = wfMsgForContent( 'revertpage', $target->getUserText(), $from );
 2261+ if( empty( $summary ) )
 2262+ $summary = wfMsgForContent( 'revertpage', $target->getUserText(), $from );
22632263
2264 - # Save it!
 2264+ # Save
22652265 $flags = EDIT_UPDATE | EDIT_MINOR;
2266 - if($bot)
 2266+ if( $bot )
22672267 $flags |= EDIT_FORCE_BOT;
2268 - if(!$this->doEdit( $target->getText(), $newComment, $flags))
2269 - return self::EDIT_FAILED;
 2268+ $this->doEdit( $target->getText(), $summary, $flags );
22702269
2271 - if(is_null($info))
2272 - // Save time
2273 - return self::SUCCESS;
2274 -
2275 - $info['title'] = $this->mTitle->getPrefixedText();
2276 - $info['pageid'] = $current->getPage();
2277 - $info['summary'] = $newComment;
2278 - // NOTE: If the rollback turned out to be a null edit, revid and old_revid will be equal
2279 - $info['revid'] = $this->mTitle->getLatestRevID(); // The revid of your rollback
2280 - $info['old_revid'] = $current->getId(); // The revid of the last edit before your rollback
2281 - $info['last_revid'] = $s->rev_id; // The revid of the last edit that was not rolled back
2282 - $info['user'] = $fromP; // The name of the victim
2283 - $info['userid'] = $user; // And their userid
2284 - $info['to'] = $target->getUserText(); // The user whose last version was reverted to
2285 - if($bot)
2286 - $info['bot'] = "";
 2270+ $resultDetails = array(
 2271+ 'summary' => $summary,
 2272+ 'current' => $current,
 2273+ 'target' => $target
 2274+ );
22872275 return self::SUCCESS;
22882276 }
22892277
2290 - /** UI entry point for rollbacks. Relies on doRollback() to do the hard work */
 2278+ /**
 2279+ * User interface for rollback operations
 2280+ */
22912281 function rollback() {
22922282 global $wgUser, $wgOut, $wgRequest, $wgUseRCPatrol;
22932283
2294 - // Basically, we just call doRollback() and interpret its return value
2295 - $info = array();
2296 - $retval = $this->doRollback($wgRequest->getVal('from'), $wgRequest->getVal('token'), $wgRequest->getBool('bot'),
2297 - $wgRequest->getText('summary'), &$info);
2298 - switch($retval)
2299 - {
2300 - default:
2301 - throw new MWException( "Unknown retval $retval" );
 2284+ $details = null;
 2285+ $result = $this->doRollback(
 2286+ $wgRequest->getVal( 'from' ),
 2287+ $wgRequest->getText( 'summary' ),
 2288+ $wgRequest->getVal( 'token' ),
 2289+ $wgRequest->getBool( 'bot' ),
 2290+ $details
 2291+ );
 2292+
 2293+ switch( $result ) {
 2294+ case self::BLOCKED:
 2295+ $wgOut->blockedPage();
23022296 break;
2303 - case self::SUCCESS:
2304 - case self::EDIT_FAILED: // Is ignored
2305 - $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
2306 - $wgOut->setRobotpolicy( 'noindex,nofollow' );
2307 - $wgOut->addHTML( '<h2>' . htmlspecialchars( $info['summary'] ) . "</h2>\n<hr />\n" );
2308 - $this->doRedirect(true);
2309 - $wgOut->returnToMain(false);
2310 - break;
23112297 case self::PERM_DENIED:
2312 - $wgOut->permissionRequired('rollback');
 2298+ $wgOut->permissionRequired( 'rollback' );
23132299 break;
2314 - case self::BLOCKED:
2315 - $wgOut->blockedPage();
2316 - break;
23172300 case self::READONLY:
2318 - $wgOut->readOnlyPage($this->getContent());
 2301+ $wgOut->readOnlyPage( $this->getContent() );
23192302 break;
23202303 case self::BAD_TOKEN:
2321 - $wgOut->setPageTitle(wfMsg('rollbackfailed'));
2322 - $wgOut->addWikiText(wfMsg('sessionfailure'));
 2304+ $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) );
 2305+ $wgOut->addWikiText( wfMsg( 'sessionfailure' ) );
23232306 break;
23242307 case self::BAD_TITLE:
2325 - $wgOut->addHTML(wfMsg('notanarticle'));
 2308+ $wgOut->addHtml( wfMsg( 'notanarticle' ) );
23262309 break;
2327 - case self::ALREADYROLLED:
2328 - $wgOut->setPageTitle(wfMsg('rollbackfailed'));
2329 - $wgOut->addWikiText(wfMsg('alreadyrolled',
2330 - htmlspecialchars($this->mTitle->getPrefixedText()),
2331 - htmlspecialchars($wgRequest->getVal('from')),
2332 - htmlspecialchars($info['usertext'])));
2333 - if($info['comment'] != '')
2334 - $wgOut->addHTML(wfMsg('editcomment',
2335 - $wgUser->getSkin()->formatComment($info['comment'])));
 2310+ case self::ALREADY_ROLLED:
 2311+ $current = $details['current'];
 2312+ $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) );
 2313+ $wgOut->addWikiText(
 2314+ wfMsg( 'alreadyrolled',
 2315+ htmlspecialchars( $this->mTitle->getPrefixedText() ),
 2316+ htmlspecialchars( $wgRequest->getVal( 'from' ) ),
 2317+ htmlspecialchars( $current->getUserText() )
 2318+ )
 2319+ );
 2320+ if( $current->getComment() != '' ) {
 2321+ $wgOut->addHtml( wfMsg( 'editcomment',
 2322+ $wgUser->getSkin()->formatComment( $current->getComment() ) ) );
 2323+ }
23362324 break;
23372325 case self::ONLY_AUTHOR:
2338 - $wgOut->setPageTitle(wfMsg('rollbackfailed'));
2339 - $wgOut->addHTML(wfMsg('cantrollback'));
 2326+ $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) );
 2327+ $wgOut->addHtml( wfMsg( 'cantrollback' ) );
23402328 break;
 2329+ case self::SUCCESS:
 2330+ $current = $details['current'];
 2331+ $target = $details['target'];
 2332+ $wgOut->setPageTitle( wfMsg( 'actioncomplete' ) );
 2333+ $wgOut->setRobotPolicy( 'noindex,nofollow' );
 2334+ $old = $wgUser->getSkin()->userLink( $current->getUser(), $current->getUserText() )
 2335+ . $wgUser->getSkin()->userToolLinks( $current->getUser(), $current->getUserText() );
 2336+ $new = $wgUser->getSkin()->userLink( $target->getUser(), $target->getUserText() )
 2337+ . $wgUser->getSkin()->userToolLinks( $target->getUser(), $target->getUserText() );
 2338+ $wgOut->addHtml( wfMsgExt( 'rollback-success', array( 'parse', 'replaceafter' ), $old, $new ) );
 2339+ $wgOut->returnToMain( false, $this->mTitle );
 2340+ break;
 2341+ default:
 2342+ throw new MWException( __METHOD__ . ": Unknown return value `{$retval}`" );
23412343 }
23422344 }
23432345
@@ -2803,16 +2805,22 @@
28042806 $page = $this->mTitle->getSubjectPage();
28052807
28062808 $wgOut->setPagetitle( $page->getPrefixedText() );
2807 - $wgOut->setSubtitle( wfMsg( 'infosubtitle' ));
 2809+ $wgOut->setPageTitleActionText( wfMsg( 'info_short' ) );
 2810+ $wgOut->setSubtitle( wfMsg( 'infosubtitle' ) );
28082811
2809 - # first, see if the page exists at all.
2810 - $exists = $page->getArticleId() != 0;
2811 - if( !$exists ) {
2812 - if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
2813 - $wgOut->addHTML(wfMsgWeirdKey ( $this->mTitle->getText() ) );
 2812+ if( !$this->mTitle->exists() ) {
 2813+ $wgOut->addHtml( '<div class="noarticletext">' );
 2814+ if( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
 2815+ // This doesn't quite make sense; the user is asking for
 2816+ // information about the _page_, not the message... -- RC
 2817+ $wgOut->addHtml( htmlspecialchars( wfMsgWeirdKey( $this->mTitle->getText() ) ) );
28142818 } else {
2815 - $wgOut->addHTML(wfMsg( $wgUser->isLoggedIn() ? 'noarticletext' : 'noarticletextanon' ) );
 2819+ $msg = $wgUser->isLoggedIn()
 2820+ ? 'noarticletext'
 2821+ : 'noarticletextanon';
 2822+ $wgOut->addHtml( wfMsgExt( $msg, 'parse' ) );
28162823 }
 2824+ $wgOut->addHtml( '</div>' );
28172825 } else {
28182826 $dbr = wfGetDB( DB_SLAVE );
28192827 $wl_clause = array(
Index: branches/apiedit/phase3/includes/api/ApiQueryUserInfo.php
@@ -0,0 +1,134 @@
 2+<?php
 3+
 4+/*
 5+ * Created on July 30, 2007
 6+ *
 7+ * API for MediaWiki 1.8+
 8+ *
 9+ * Copyright (C) 2007 Yuri Astrakhan <Firstname><Lastname>@gmail.com
 10+ *
 11+ * This program is free software; you can redistribute it and/or modify
 12+ * it under the terms of the GNU General Public License as published by
 13+ * the Free Software Foundation; either version 2 of the License, or
 14+ * (at your option) any later version.
 15+ *
 16+ * This program is distributed in the hope that it will be useful,
 17+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 19+ * GNU General Public License for more details.
 20+ *
 21+ * You should have received a copy of the GNU General Public License along
 22+ * with this program; if not, write to the Free Software Foundation, Inc.,
 23+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 24+ * http://www.gnu.org/copyleft/gpl.html
 25+ */
 26+
 27+if (!defined('MEDIAWIKI')) {
 28+ // Eclipse helper - will be ignored in production
 29+ require_once ('ApiQueryBase.php');
 30+}
 31+
 32+/**
 33+ * Query module to get information about the currently logged-in user
 34+ *
 35+ * @addtogroup API
 36+ */
 37+class ApiQueryUserInfo extends ApiQueryBase {
 38+
 39+ public function __construct($query, $moduleName) {
 40+ parent :: __construct($query, $moduleName, 'ui');
 41+ }
 42+
 43+ public function execute() {
 44+
 45+ global $wgUser;
 46+
 47+ $params = $this->extractRequestParams();
 48+ $result = $this->getResult();
 49+
 50+ $vals = array();
 51+ $vals['name'] = $wgUser->getName();
 52+
 53+ if( $wgUser->isAnon() ) $vals['anon'] = '';
 54+
 55+ if (!is_null($params['prop'])) {
 56+ $prop = array_flip($params['prop']);
 57+ if (isset($prop['blockinfo'])) {
 58+ if ($wgUser->isBlocked()) {
 59+ $id = $wgUser->blockedBy();
 60+ $vals['blockedby'] = is_numeric($id) ? User::whoIs($id) : $id;
 61+ $vals['blockreason'] = $wgUser->blockedFor();
 62+ }
 63+ }
 64+ if (isset($prop['hasmsg']) && $wgUser->getNewtalk()) {
 65+ $vals['messages'] = '';
 66+ }
 67+ if (isset($prop['groups'])) {
 68+ $vals['groups'] = $wgUser->getGroups();
 69+ $result->setIndexedTagName($vals['groups'], 'g'); // even if empty
 70+ }
 71+ if (isset($prop['rights'])) {
 72+ $vals['rights'] = $wgUser->getRights();
 73+ $result->setIndexedTagName($vals['rights'], 'r'); // even if empty
 74+ }
 75+ }
 76+
 77+ if (!empty($params['option'])) {
 78+ foreach( $params['option'] as $option ) {
 79+ if (empty($option))
 80+ $this->dieUsage('Empty value is not allowed for the option parameter', 'option');
 81+ $vals['options'][$option] = $wgUser->getOption($option);
 82+ }
 83+ }
 84+
 85+ $result->addValue(null, $this->getModuleName(), $vals);
 86+ }
 87+
 88+ protected function getAllowedParams() {
 89+ return array (
 90+ 'prop' => array (
 91+ ApiBase :: PARAM_DFLT => NULL,
 92+ ApiBase :: PARAM_ISMULTI => true,
 93+ ApiBase :: PARAM_TYPE => array (
 94+ 'blockinfo',
 95+ 'hasmsg',
 96+ 'groups',
 97+ 'rights',
 98+ )),
 99+ 'option' => array (
 100+ ApiBase :: PARAM_DFLT => NULL,
 101+ ApiBase :: PARAM_ISMULTI => true,
 102+ ),
 103+ );
 104+ }
 105+
 106+ protected function getParamDescription() {
 107+ return array (
 108+ 'prop' => array(
 109+ 'What pieces of information to include',
 110+ ' blockinfo - tags if the user is blocked, by whom, and for what reason',
 111+ ' hasmsg - adds a tag "message" if user has pending messages',
 112+ ' groups - lists all the groups the current user belongs to',
 113+ ' rights - lists of all rights the current user has',
 114+ ),
 115+ 'option' => 'A list of user preference options to get',
 116+ );
 117+ }
 118+
 119+ protected function getDescription() {
 120+ return 'Get information about the current user';
 121+ }
 122+
 123+ protected function getExamples() {
 124+ return array (
 125+ 'api.php?action=query&meta=userinfo',
 126+ 'api.php?action=query&meta=userinfo&uiprop=blockinfo|groups|rights|hasmsg',
 127+ 'api.php?action=query&meta=userinfo&uioption=rememberpassword',
 128+ );
 129+ }
 130+
 131+ public function getVersion() {
 132+ return __CLASS__ . ': $Id: ApiQueryUserInfo.php 24494 2007-07-31 17:53:37Z yurik $';
 133+ }
 134+}
 135+
Property changes on: branches/apiedit/phase3/includes/api/ApiQueryUserInfo.php
___________________________________________________________________
Added: svn:eol-style
1136 + native
Index: branches/apiedit/phase3/includes/SpecialUndelete.php
@@ -23,6 +23,7 @@
2424 */
2525 class PageArchive {
2626 protected $title;
 27+ var $fileStatus;
2728
2829 function __construct( $title ) {
2930 if( is_null( $title ) ) {
@@ -269,10 +270,10 @@
270271 $dbw = wfGetDB(DB_MASTER);
271272 $dbw->begin();
272273 $restoreAll = empty( $timestamps ) && empty( $fileVersions );
273 -
 274+
274275 $restoreText = $restoreAll || !empty( $timestamps );
275276 $restoreFiles = $restoreAll || !empty( $fileVersions );
276 -
 277+
277278 if( $restoreFiles && $this->title->getNamespace() == NS_IMAGE ) {
278279 $img = wfLocalFile( $this->title );
279280 $this->fileStatus = $img->restore( $fileVersions );
@@ -280,7 +281,7 @@
281282 } else {
282283 $filesRestored = 0;
283284 }
284 -
 285+
285286 if( $restoreText ) {
286287 $textRestored = $this->undeleteRevisions( $timestamps );
287288 if($textRestored < 0) // It must be one of UNDELETE_*
@@ -291,7 +292,7 @@
292293 } else {
293294 $textRestored = 0;
294295 }
295 -
 296+
296297 // Touch the log!
297298 global $wgContLang;
298299 $log = new LogPage( 'delete' );
@@ -461,6 +462,7 @@
462463 return $restored;
463464 }
464465
 466+ function getFileStatus() { return $this->fileStatus; }
465467 }
466468
467469 /**
@@ -744,8 +746,13 @@
745747 $logViewer = new LogViewer(
746748 new LogReader(
747749 new FauxRequest(
748 - array( 'page' => $this->mTargetObj->getPrefixedText(),
749 - 'type' => 'delete' ) ) ) );
 750+ array(
 751+ 'page' => $this->mTargetObj->getPrefixedText(),
 752+ 'type' => 'delete'
 753+ )
 754+ )
 755+ ), LogViewer::NO_ACTION_LINK
 756+ );
750757 $logViewer->showList( $wgOut );
751758
752759 if( $this->mAllowed && ( $haveRevisions || $haveFiles ) ) {
@@ -818,7 +825,7 @@
819826 }
820827
821828 if( $haveFiles ) {
822 - $wgOut->addHtml( "<h2>" . wfMsgHtml( 'imghistory' ) . "</h2>\n" );
 829+ $wgOut->addHtml( "<h2>" . wfMsgHtml( 'filehist' ) . "</h2>\n" );
823830 $wgOut->addHtml( "<ul>" );
824831 while( $row = $files->fetchObject() ) {
825832 $ts = wfTimestamp( TS_MW, $row->fa_timestamp );
@@ -868,15 +875,24 @@
869876 $this->mTargetTimestamp,
870877 $this->mComment,
871878 $this->mFileVersions );
872 -
 879+
873880 if( is_array($ok) ) {
874881 $skin = $wgUser->getSkin();
875882 $link = $skin->makeKnownLinkObj( $this->mTargetObj );
876883 $wgOut->addHtml( wfMsgWikiHtml( 'undeletedpage', $link ) );
877 - return true;
 884+ } else {
 885+ $wgOut->showFatalError( wfMsg( "cannotundelete" ) );
878886 }
 887+
 888+ // Show file deletion warnings and errors
 889+ $status = $archive->getFileStatus();
 890+ if ( $status && !$status->isGood() ) {
 891+ $wgOut->addWikiText( $status->getWikiText( 'undelete-error-short', 'undelete-error-long' ) );
 892+ }
 893+ } else {
 894+ $wgOut->showFatalError( wfMsg( "cannotundelete" ) );
879895 }
880 - $wgOut->showFatalError( wfMsg( "cannotundelete" ) );
 896+
881897 return false;
882898 }
883899 }

Status & tagging log