r102862 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r102861‎ | r102862 | r102863 >
Date:13:47, 12 November 2011
Author:ialex
Status:ok
Tags:
Comment:
Moved methods around to group them by functionnality
Modified paths:
  • /trunk/phase3/includes/EditPage.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/EditPage.php
@@ -161,201 +161,6 @@
162162 }
163163 }
164164
165 - /**
166 - * Fetch initial editing page content.
167 - *
168 - * @param $def_text string
169 - * @return mixed string on success, $def_text for invalid sections
170 - * @private
171 - */
172 - function getContent( $def_text = '' ) {
173 - global $wgOut, $wgRequest, $wgParser;
174 -
175 - wfProfileIn( __METHOD__ );
176 - # Get variables from query string :P
177 - $section = $wgRequest->getVal( 'section' );
178 -
179 - $preload = $wgRequest->getVal( 'preload',
180 - // Custom preload text for new sections
181 - $section === 'new' ? 'MediaWiki:addsection-preload' : '' );
182 - $undoafter = $wgRequest->getVal( 'undoafter' );
183 - $undo = $wgRequest->getVal( 'undo' );
184 -
185 - // For message page not locally set, use the i18n message.
186 - // For other non-existent articles, use preload text if any.
187 - if ( !$this->mTitle->exists() ) {
188 - if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
189 - # If this is a system message, get the default text.
190 - $text = $this->mTitle->getDefaultMessageText();
191 - if( $text === false ) {
192 - $text = $this->getPreloadedText( $preload );
193 - }
194 - } else {
195 - # If requested, preload some text.
196 - $text = $this->getPreloadedText( $preload );
197 - }
198 - // For existing pages, get text based on "undo" or section parameters.
199 - } else {
200 - $text = $this->mArticle->getContent();
201 - if ( $undo > 0 && $undoafter > 0 && $undo < $undoafter ) {
202 - # If they got undoafter and undo round the wrong way, switch them
203 - list( $undo, $undoafter ) = array( $undoafter, $undo );
204 - }
205 - if ( $undo > 0 && $undo > $undoafter ) {
206 - # Undoing a specific edit overrides section editing; section-editing
207 - # doesn't work with undoing.
208 - if ( $undoafter ) {
209 - $undorev = Revision::newFromId( $undo );
210 - $oldrev = Revision::newFromId( $undoafter );
211 - } else {
212 - $undorev = Revision::newFromId( $undo );
213 - $oldrev = $undorev ? $undorev->getPrevious() : null;
214 - }
215 -
216 - # Sanity check, make sure it's the right page,
217 - # the revisions exist and they were not deleted.
218 - # Otherwise, $text will be left as-is.
219 - if ( !is_null( $undorev ) && !is_null( $oldrev ) &&
220 - $undorev->getPage() == $oldrev->getPage() &&
221 - $undorev->getPage() == $this->mArticle->getID() &&
222 - !$undorev->isDeleted( Revision::DELETED_TEXT ) &&
223 - !$oldrev->isDeleted( Revision::DELETED_TEXT ) ) {
224 -
225 - $undotext = $this->mArticle->getUndoText( $undorev, $oldrev );
226 - if ( $undotext === false ) {
227 - # Warn the user that something went wrong
228 - $this->editFormPageTop .= $wgOut->parse( '<div class="error mw-undo-failure">' .
229 - wfMsgNoTrans( 'undo-failure' ) . '</div>', true, /* interface */true );
230 - } else {
231 - $text = $undotext;
232 - # Inform the user of our success and set an automatic edit summary
233 - $this->editFormPageTop .= $wgOut->parse( '<div class="mw-undo-success">' .
234 - wfMsgNoTrans( 'undo-success' ) . '</div>', true, /* interface */true );
235 - $firstrev = $oldrev->getNext();
236 - # If we just undid one rev, use an autosummary
237 - if ( $firstrev->getId() == $undo ) {
238 - $undoSummary = wfMsgForContent( 'undo-summary', $undo, $undorev->getUserText() );
239 - if ( $this->summary === '' ) {
240 - $this->summary = $undoSummary;
241 - } else {
242 - $this->summary = $undoSummary . wfMsgForContent( 'colon-separator' ) . $this->summary;
243 - }
244 - $this->undidRev = $undo;
245 - }
246 - $this->formtype = 'diff';
247 - }
248 - } else {
249 - // Failed basic sanity checks.
250 - // Older revisions may have been removed since the link
251 - // was created, or we may simply have got bogus input.
252 - $this->editFormPageTop .= $wgOut->parse( '<div class="error mw-undo-norev">' .
253 - wfMsgNoTrans( 'undo-norev' ) . '</div>', true, /* interface */true );
254 - }
255 - } elseif ( $section != '' ) {
256 - if ( $section == 'new' ) {
257 - $text = $this->getPreloadedText( $preload );
258 - } else {
259 - // Get section edit text (returns $def_text for invalid sections)
260 - $text = $wgParser->getSection( $text, $section, $def_text );
261 - }
262 - }
263 - }
264 -
265 - wfProfileOut( __METHOD__ );
266 - return $text;
267 - }
268 -
269 - /**
270 - * Use this method before edit() to preload some text into the edit box
271 - *
272 - * @param $text string
273 - */
274 - public function setPreloadedText( $text ) {
275 - $this->mPreloadText = $text;
276 - }
277 -
278 - /**
279 - * Get the contents to be preloaded into the box, either set by
280 - * an earlier setPreloadText() or by loading the given page.
281 - *
282 - * @param $preload String: representing the title to preload from.
283 - * @return String
284 - */
285 - protected function getPreloadedText( $preload ) {
286 - global $wgUser, $wgParser;
287 - if ( !empty( $this->mPreloadText ) ) {
288 - return $this->mPreloadText;
289 - } elseif ( $preload !== '' ) {
290 - $title = Title::newFromText( $preload );
291 - # Check for existence to avoid getting MediaWiki:Noarticletext
292 - if ( isset( $title ) && $title->exists() && $title->userCanRead() ) {
293 - $article = new Article( $title );
294 -
295 - if ( $article->isRedirect() ) {
296 - $title = Title::newFromRedirectRecurse( $article->getContent() );
297 - # Redirects to missing titles are displayed, to hidden pages are followed
298 - # Copying observed behaviour from ?action=view
299 - if ( $title->exists() ) {
300 - if ($title->userCanRead() ) {
301 - $article = new Article( $title );
302 - } else {
303 - return "";
304 - }
305 - }
306 - }
307 - $parserOptions = ParserOptions::newFromUser( $wgUser );
308 - return $wgParser->getPreloadText( $article->getContent(), $title, $parserOptions );
309 - }
310 - }
311 - return '';
312 - }
313 -
314 - /**
315 - * Check if a page was deleted while the user was editing it, before submit.
316 - * Note that we rely on the logging table, which hasn't been always there,
317 - * but that doesn't matter, because this only applies to brand new
318 - * deletes.
319 - */
320 - protected function wasDeletedSinceLastEdit() {
321 - if ( $this->deletedSinceEdit !== null ) {
322 - return $this->deletedSinceEdit;
323 - }
324 -
325 - $this->deletedSinceEdit = false;
326 -
327 - if ( $this->mTitle->isDeletedQuick() ) {
328 - $this->lastDelete = $this->getLastDelete();
329 - if ( $this->lastDelete ) {
330 - $deleteTime = wfTimestamp( TS_MW, $this->lastDelete->log_timestamp );
331 - if ( $deleteTime > $this->starttime ) {
332 - $this->deletedSinceEdit = true;
333 - }
334 - }
335 - }
336 -
337 - return $this->deletedSinceEdit;
338 - }
339 -
340 - /**
341 - * Checks whether the user entered a skin name in uppercase,
342 - * e.g. "User:Example/Monobook.css" instead of "monobook.css"
343 - *
344 - * @return bool
345 - */
346 - protected function isWrongCaseCssJsPage() {
347 - if( $this->mTitle->isCssJsSubpage() ) {
348 - $name = $this->mTitle->getSkinFromCssJsSubpage();
349 - $skins = array_merge(
350 - array_keys( Skin::getSkinNames() ),
351 - array( 'common' )
352 - );
353 - return !in_array( $name, $skins )
354 - && in_array( strtolower( $name ), $skins );
355 - } else {
356 - return false;
357 - }
358 - }
359 -
360165 function submit() {
361166 $this->edit();
362167 }
@@ -643,26 +448,33 @@
644449 }
645450
646451 /**
647 - * Does this EditPage class support section editing?
648 - * This is used by EditPage subclasses to indicate their ui cannot handle section edits
 452+ * Checks whether the user entered a skin name in uppercase,
 453+ * e.g. "User:Example/Monobook.css" instead of "monobook.css"
649454 *
650455 * @return bool
651456 */
652 - protected function isSectionEditSupported() {
653 - return true;
 457+ protected function isWrongCaseCssJsPage() {
 458+ if( $this->mTitle->isCssJsSubpage() ) {
 459+ $name = $this->mTitle->getSkinFromCssJsSubpage();
 460+ $skins = array_merge(
 461+ array_keys( Skin::getSkinNames() ),
 462+ array( 'common' )
 463+ );
 464+ return !in_array( $name, $skins )
 465+ && in_array( strtolower( $name ), $skins );
 466+ } else {
 467+ return false;
 468+ }
654469 }
655470
656471 /**
657 - * Returns the URL to use in the form's action attribute.
658 - * This is used by EditPage subclasses when simply customizing the action
659 - * variable in the constructor is not enough. This can be used when the
660 - * EditPage lives inside of a Special page rather than a custom page action.
 472+ * Does this EditPage class support section editing?
 473+ * This is used by EditPage subclasses to indicate their ui cannot handle section edits
661474 *
662 - * @param $title Title object for which is being edited (where we go to for &action= links)
663 - * @return string
 475+ * @return bool
664476 */
665 - protected function getActionURL( Title $title ) {
666 - return $title->getLocalURL( array( 'action' => $this->action ) );
 477+ protected function isSectionEditSupported() {
 478+ return true;
667479 }
668480
669481 /**
@@ -825,6 +637,186 @@
826638 }
827639
828640 /**
 641+ * Initialise form fields in the object
 642+ * Called on the first invocation, e.g. when a user clicks an edit link
 643+ * @return bool -- if the requested section is valid
 644+ */
 645+ function initialiseForm() {
 646+ global $wgUser;
 647+ $this->edittime = $this->mArticle->getTimestamp();
 648+ $this->textbox1 = $this->getContent( false );
 649+ // activate checkboxes if user wants them to be always active
 650+ # Sort out the "watch" checkbox
 651+ if ( $wgUser->getOption( 'watchdefault' ) ) {
 652+ # Watch all edits
 653+ $this->watchthis = true;
 654+ } elseif ( $wgUser->getOption( 'watchcreations' ) && !$this->mTitle->exists() ) {
 655+ # Watch creations
 656+ $this->watchthis = true;
 657+ } elseif ( $this->mTitle->userIsWatching() ) {
 658+ # Already watched
 659+ $this->watchthis = true;
 660+ }
 661+ if ( $wgUser->getOption( 'minordefault' ) && !$this->isNew ) {
 662+ $this->minoredit = true;
 663+ }
 664+ if ( $this->textbox1 === false ) {
 665+ return false;
 666+ }
 667+ wfProxyCheck();
 668+ return true;
 669+ }
 670+
 671+ /**
 672+ * Fetch initial editing page content.
 673+ *
 674+ * @param $def_text string
 675+ * @return mixed string on success, $def_text for invalid sections
 676+ * @private
 677+ */
 678+ function getContent( $def_text = '' ) {
 679+ global $wgOut, $wgRequest, $wgParser;
 680+
 681+ wfProfileIn( __METHOD__ );
 682+ # Get variables from query string :P
 683+ $section = $wgRequest->getVal( 'section' );
 684+
 685+ $preload = $wgRequest->getVal( 'preload',
 686+ // Custom preload text for new sections
 687+ $section === 'new' ? 'MediaWiki:addsection-preload' : '' );
 688+ $undoafter = $wgRequest->getVal( 'undoafter' );
 689+ $undo = $wgRequest->getVal( 'undo' );
 690+
 691+ // For message page not locally set, use the i18n message.
 692+ // For other non-existent articles, use preload text if any.
 693+ if ( !$this->mTitle->exists() ) {
 694+ if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
 695+ # If this is a system message, get the default text.
 696+ $text = $this->mTitle->getDefaultMessageText();
 697+ if( $text === false ) {
 698+ $text = $this->getPreloadedText( $preload );
 699+ }
 700+ } else {
 701+ # If requested, preload some text.
 702+ $text = $this->getPreloadedText( $preload );
 703+ }
 704+ // For existing pages, get text based on "undo" or section parameters.
 705+ } else {
 706+ $text = $this->mArticle->getContent();
 707+ if ( $undo > 0 && $undoafter > 0 && $undo < $undoafter ) {
 708+ # If they got undoafter and undo round the wrong way, switch them
 709+ list( $undo, $undoafter ) = array( $undoafter, $undo );
 710+ }
 711+ if ( $undo > 0 && $undo > $undoafter ) {
 712+ # Undoing a specific edit overrides section editing; section-editing
 713+ # doesn't work with undoing.
 714+ if ( $undoafter ) {
 715+ $undorev = Revision::newFromId( $undo );
 716+ $oldrev = Revision::newFromId( $undoafter );
 717+ } else {
 718+ $undorev = Revision::newFromId( $undo );
 719+ $oldrev = $undorev ? $undorev->getPrevious() : null;
 720+ }
 721+
 722+ # Sanity check, make sure it's the right page,
 723+ # the revisions exist and they were not deleted.
 724+ # Otherwise, $text will be left as-is.
 725+ if ( !is_null( $undorev ) && !is_null( $oldrev ) &&
 726+ $undorev->getPage() == $oldrev->getPage() &&
 727+ $undorev->getPage() == $this->mArticle->getID() &&
 728+ !$undorev->isDeleted( Revision::DELETED_TEXT ) &&
 729+ !$oldrev->isDeleted( Revision::DELETED_TEXT ) ) {
 730+
 731+ $undotext = $this->mArticle->getUndoText( $undorev, $oldrev );
 732+ if ( $undotext === false ) {
 733+ # Warn the user that something went wrong
 734+ $this->editFormPageTop .= $wgOut->parse( '<div class="error mw-undo-failure">' .
 735+ wfMsgNoTrans( 'undo-failure' ) . '</div>', true, /* interface */true );
 736+ } else {
 737+ $text = $undotext;
 738+ # Inform the user of our success and set an automatic edit summary
 739+ $this->editFormPageTop .= $wgOut->parse( '<div class="mw-undo-success">' .
 740+ wfMsgNoTrans( 'undo-success' ) . '</div>', true, /* interface */true );
 741+ $firstrev = $oldrev->getNext();
 742+ # If we just undid one rev, use an autosummary
 743+ if ( $firstrev->getId() == $undo ) {
 744+ $undoSummary = wfMsgForContent( 'undo-summary', $undo, $undorev->getUserText() );
 745+ if ( $this->summary === '' ) {
 746+ $this->summary = $undoSummary;
 747+ } else {
 748+ $this->summary = $undoSummary . wfMsgForContent( 'colon-separator' ) . $this->summary;
 749+ }
 750+ $this->undidRev = $undo;
 751+ }
 752+ $this->formtype = 'diff';
 753+ }
 754+ } else {
 755+ // Failed basic sanity checks.
 756+ // Older revisions may have been removed since the link
 757+ // was created, or we may simply have got bogus input.
 758+ $this->editFormPageTop .= $wgOut->parse( '<div class="error mw-undo-norev">' .
 759+ wfMsgNoTrans( 'undo-norev' ) . '</div>', true, /* interface */true );
 760+ }
 761+ } elseif ( $section != '' ) {
 762+ if ( $section == 'new' ) {
 763+ $text = $this->getPreloadedText( $preload );
 764+ } else {
 765+ // Get section edit text (returns $def_text for invalid sections)
 766+ $text = $wgParser->getSection( $text, $section, $def_text );
 767+ }
 768+ }
 769+ }
 770+
 771+ wfProfileOut( __METHOD__ );
 772+ return $text;
 773+ }
 774+
 775+ /**
 776+ * Use this method before edit() to preload some text into the edit box
 777+ *
 778+ * @param $text string
 779+ */
 780+ public function setPreloadedText( $text ) {
 781+ $this->mPreloadText = $text;
 782+ }
 783+
 784+ /**
 785+ * Get the contents to be preloaded into the box, either set by
 786+ * an earlier setPreloadText() or by loading the given page.
 787+ *
 788+ * @param $preload String: representing the title to preload from.
 789+ * @return String
 790+ */
 791+ protected function getPreloadedText( $preload ) {
 792+ global $wgUser, $wgParser;
 793+ if ( !empty( $this->mPreloadText ) ) {
 794+ return $this->mPreloadText;
 795+ } elseif ( $preload !== '' ) {
 796+ $title = Title::newFromText( $preload );
 797+ # Check for existence to avoid getting MediaWiki:Noarticletext
 798+ if ( isset( $title ) && $title->exists() && $title->userCanRead() ) {
 799+ $article = new Article( $title );
 800+
 801+ if ( $article->isRedirect() ) {
 802+ $title = Title::newFromRedirectRecurse( $article->getContent() );
 803+ # Redirects to missing titles are displayed, to hidden pages are followed
 804+ # Copying observed behaviour from ?action=view
 805+ if ( $title->exists() ) {
 806+ if ($title->userCanRead() ) {
 807+ $article = new Article( $title );
 808+ } else {
 809+ return "";
 810+ }
 811+ }
 812+ }
 813+ $parserOptions = ParserOptions::newFromUser( $wgUser );
 814+ return $wgParser->getPreloadText( $article->getContent(), $title, $parserOptions );
 815+ }
 816+ }
 817+ return '';
 818+ }
 819+
 820+ /**
829821 * Make sure the form isn't faking a user's credentials.
830822 *
831823 * @param $request WebRequest
@@ -840,86 +832,90 @@
841833 }
842834
843835 /**
844 - * Show all applicable editing introductions
 836+ * Attempt submission
 837+ * @return bool false if output is done, true if the rest of the form should be displayed
845838 */
846 - protected function showIntro() {
847 - global $wgOut, $wgUser;
848 - if ( $this->suppressIntro ) {
849 - return;
850 - }
 839+ function attemptSave() {
 840+ global $wgUser, $wgOut;
851841
852 - $namespace = $this->mTitle->getNamespace();
 842+ $resultDetails = false;
 843+ # Allow bots to exempt some edits from bot flagging
 844+ $bot = $wgUser->isAllowed( 'bot' ) && $this->bot;
 845+ $status = $this->internalAttemptSave( $resultDetails, $bot );
 846+ // FIXME: once the interface for internalAttemptSave() is made nicer, this should use the message in $status
853847
854 - if ( $namespace == NS_MEDIAWIKI ) {
855 - # Show a warning if editing an interface message
856 - $wgOut->wrapWikiMsg( "<div class='mw-editinginterface'>\n$1\n</div>", 'editinginterface' );
 848+ if ( $status->value == self::AS_SUCCESS_UPDATE || $status->value == self::AS_SUCCESS_NEW_ARTICLE ) {
 849+ $this->didSave = true;
857850 }
858851
859 - # Show a warning message when someone creates/edits a user (talk) page but the user does not exist
860 - # Show log extract when the user is currently blocked
861 - if ( $namespace == NS_USER || $namespace == NS_USER_TALK ) {
862 - $parts = explode( '/', $this->mTitle->getText(), 2 );
863 - $username = $parts[0];
864 - $user = User::newFromName( $username, false /* allow IP users*/ );
865 - $ip = User::isIP( $username );
866 - if ( !$user->isLoggedIn() && !$ip ) { # User does not exist
867 - $wgOut->wrapWikiMsg( "<div class=\"mw-userpage-userdoesnotexist error\">\n$1\n</div>",
868 - array( 'userpage-userdoesnotexist', wfEscapeWikiText( $username ) ) );
869 - } elseif ( $user->isBlocked() ) { # Show log extract if the user is currently blocked
870 - LogEventsList::showLogExtract(
871 - $wgOut,
872 - 'block',
873 - $user->getUserPage(),
874 - '',
875 - array(
876 - 'lim' => 1,
877 - 'showIfEmpty' => false,
878 - 'msgKey' => array(
879 - 'blocked-notice-logextract',
880 - $user->getName() # Support GENDER in notice
881 - )
882 - )
883 - );
884 - }
885 - }
886 - # Try to add a custom edit intro, or use the standard one if this is not possible.
887 - if ( !$this->showCustomIntro() && !$this->mTitle->exists() ) {
888 - if ( $wgUser->isLoggedIn() ) {
889 - $wgOut->wrapWikiMsg( "<div class=\"mw-newarticletext\">\n$1\n</div>", 'newarticletext' );
890 - } else {
891 - $wgOut->wrapWikiMsg( "<div class=\"mw-newarticletextanon\">\n$1\n</div>", 'newarticletextanon' );
892 - }
893 - }
894 - # Give a notice if the user is editing a deleted/moved page...
895 - if ( !$this->mTitle->exists() ) {
896 - LogEventsList::showLogExtract( $wgOut, array( 'delete', 'move' ), $this->mTitle,
897 - '', array( 'lim' => 10,
898 - 'conds' => array( "log_action != 'revision'" ),
899 - 'showIfEmpty' => false,
900 - 'msgKey' => array( 'recreate-moveddeleted-warn') )
901 - );
902 - }
903 - }
904 -
905 - /**
906 - * Attempt to show a custom editing introduction, if supplied
907 - *
908 - * @return bool
909 - */
910 - protected function showCustomIntro() {
911 - if ( $this->editintro ) {
912 - $title = Title::newFromText( $this->editintro );
913 - if ( $title instanceof Title && $title->exists() && $title->userCanRead() ) {
914 - global $wgOut;
915 - // Added using template syntax, to take <noinclude>'s into account.
916 - $wgOut->addWikiTextTitleTidy( '{{:' . $title->getFullText() . '}}', $this->mTitle );
 852+ switch ( $status->value ) {
 853+ case self::AS_HOOK_ERROR_EXPECTED:
 854+ case self::AS_CONTENT_TOO_BIG:
 855+ case self::AS_ARTICLE_WAS_DELETED:
 856+ case self::AS_CONFLICT_DETECTED:
 857+ case self::AS_SUMMARY_NEEDED:
 858+ case self::AS_TEXTBOX_EMPTY:
 859+ case self::AS_MAX_ARTICLE_SIZE_EXCEEDED:
 860+ case self::AS_END:
917861 return true;
918 - } else {
 862+
 863+ case self::AS_HOOK_ERROR:
 864+ case self::AS_FILTERING:
919865 return false;
920 - }
921 - } else {
922 - return false;
 866+
 867+ case self::AS_SUCCESS_NEW_ARTICLE:
 868+ $query = $resultDetails['redirect'] ? 'redirect=no' : '';
 869+ $wgOut->redirect( $this->mTitle->getFullURL( $query ) );
 870+ return false;
 871+
 872+ case self::AS_SUCCESS_UPDATE:
 873+ $extraQuery = '';
 874+ $sectionanchor = $resultDetails['sectionanchor'];
 875+
 876+ // Give extensions a chance to modify URL query on update
 877+ wfRunHooks( 'ArticleUpdateBeforeRedirect', array( $this->mArticle, &$sectionanchor, &$extraQuery ) );
 878+
 879+ if ( $resultDetails['redirect'] ) {
 880+ if ( $extraQuery == '' ) {
 881+ $extraQuery = 'redirect=no';
 882+ } else {
 883+ $extraQuery = 'redirect=no&' . $extraQuery;
 884+ }
 885+ }
 886+ $wgOut->redirect( $this->mTitle->getFullURL( $extraQuery ) . $sectionanchor );
 887+ return false;
 888+
 889+ case self::AS_BLANK_ARTICLE:
 890+ $wgOut->redirect( $this->getContextTitle()->getFullURL() );
 891+ return false;
 892+
 893+ case self::AS_SPAM_ERROR:
 894+ $this->spamPageWithContent( $resultDetails['spam'] );
 895+ return false;
 896+
 897+ case self::AS_BLOCKED_PAGE_FOR_USER:
 898+ throw new UserBlockedError( $wgUser->mBlock );
 899+
 900+ case self::AS_IMAGE_REDIRECT_ANON:
 901+ case self::AS_IMAGE_REDIRECT_LOGGED:
 902+ throw new PermissionsError( 'upload' );
 903+
 904+ case self::AS_READ_ONLY_PAGE_ANON:
 905+ case self::AS_READ_ONLY_PAGE_LOGGED:
 906+ throw new PermissionsError( 'edit' );
 907+
 908+ case self::AS_READ_ONLY_PAGE:
 909+ throw new ReadOnlyError;
 910+
 911+ case self::AS_RATE_LIMITED:
 912+ throw new ThrottledError();
 913+
 914+ case self::AS_NO_CREATE_PERMISSION:
 915+ $permission = $this->mTitle->isTalkPage() ? 'createtalk' : 'createpage';
 916+ throw new PermissionsError( $permission );
 917+
923918 }
 919+ return false;
924920 }
925921
926922 /**
@@ -1339,6 +1335,60 @@
13401336 }
13411337
13421338 /**
 1339+ * @private
 1340+ * @todo document
 1341+ *
 1342+ * @parma $editText string
 1343+ *
 1344+ * @return bool
 1345+ */
 1346+ function mergeChangesInto( &$editText ){
 1347+ wfProfileIn( __METHOD__ );
 1348+
 1349+ $db = wfGetDB( DB_MASTER );
 1350+
 1351+ // This is the revision the editor started from
 1352+ $baseRevision = $this->getBaseRevision();
 1353+ if ( is_null( $baseRevision ) ) {
 1354+ wfProfileOut( __METHOD__ );
 1355+ return false;
 1356+ }
 1357+ $baseText = $baseRevision->getText();
 1358+
 1359+ // The current state, we want to merge updates into it
 1360+ $currentRevision = Revision::loadFromTitle( $db, $this->mTitle );
 1361+ if ( is_null( $currentRevision ) ) {
 1362+ wfProfileOut( __METHOD__ );
 1363+ return false;
 1364+ }
 1365+ $currentText = $currentRevision->getText();
 1366+
 1367+ $result = '';
 1368+ if ( wfMerge( $baseText, $editText, $currentText, $result ) ) {
 1369+ $editText = $result;
 1370+ wfProfileOut( __METHOD__ );
 1371+ return true;
 1372+ } else {
 1373+ wfProfileOut( __METHOD__ );
 1374+ return false;
 1375+ }
 1376+ }
 1377+
 1378+ /**
 1379+ * @return Revision
 1380+ */
 1381+ function getBaseRevision() {
 1382+ if ( !$this->mBaseRevision ) {
 1383+ $db = wfGetDB( DB_MASTER );
 1384+ $baseRevision = Revision::loadFromTimestamp(
 1385+ $db, $this->mTitle, $this->edittime );
 1386+ return $this->mBaseRevision = $baseRevision;
 1387+ } else {
 1388+ return $this->mBaseRevision;
 1389+ }
 1390+ }
 1391+
 1392+ /**
13431393 * Check given input text against $wgSpamRegex, and return the text of the first match.
13441394 *
13451395 * @param $text string
@@ -1380,37 +1430,6 @@
13811431 return false;
13821432 }
13831433
1384 - /**
1385 - * Initialise form fields in the object
1386 - * Called on the first invocation, e.g. when a user clicks an edit link
1387 - * @return bool -- if the requested section is valid
1388 - */
1389 - function initialiseForm() {
1390 - global $wgUser;
1391 - $this->edittime = $this->mArticle->getTimestamp();
1392 - $this->textbox1 = $this->getContent( false );
1393 - // activate checkboxes if user wants them to be always active
1394 - # Sort out the "watch" checkbox
1395 - if ( $wgUser->getOption( 'watchdefault' ) ) {
1396 - # Watch all edits
1397 - $this->watchthis = true;
1398 - } elseif ( $wgUser->getOption( 'watchcreations' ) && !$this->mTitle->exists() ) {
1399 - # Watch creations
1400 - $this->watchthis = true;
1401 - } elseif ( $this->mTitle->userIsWatching() ) {
1402 - # Already watched
1403 - $this->watchthis = true;
1404 - }
1405 - if ( $wgUser->getOption( 'minordefault' ) && !$this->isNew ) {
1406 - $this->minoredit = true;
1407 - }
1408 - if ( $this->textbox1 === false ) {
1409 - return false;
1410 - }
1411 - wfProxyCheck();
1412 - return true;
1413 - }
1414 -
14151434 function setHeaders() {
14161435 global $wgOut;
14171436 $wgOut->setRobotPolicy( 'noindex,nofollow' );
@@ -1432,6 +1451,89 @@
14331452 }
14341453
14351454 /**
 1455+ * Show all applicable editing introductions
 1456+ */
 1457+ protected function showIntro() {
 1458+ global $wgOut, $wgUser;
 1459+ if ( $this->suppressIntro ) {
 1460+ return;
 1461+ }
 1462+
 1463+ $namespace = $this->mTitle->getNamespace();
 1464+
 1465+ if ( $namespace == NS_MEDIAWIKI ) {
 1466+ # Show a warning if editing an interface message
 1467+ $wgOut->wrapWikiMsg( "<div class='mw-editinginterface'>\n$1\n</div>", 'editinginterface' );
 1468+ }
 1469+
 1470+ # Show a warning message when someone creates/edits a user (talk) page but the user does not exist
 1471+ # Show log extract when the user is currently blocked
 1472+ if ( $namespace == NS_USER || $namespace == NS_USER_TALK ) {
 1473+ $parts = explode( '/', $this->mTitle->getText(), 2 );
 1474+ $username = $parts[0];
 1475+ $user = User::newFromName( $username, false /* allow IP users*/ );
 1476+ $ip = User::isIP( $username );
 1477+ if ( !$user->isLoggedIn() && !$ip ) { # User does not exist
 1478+ $wgOut->wrapWikiMsg( "<div class=\"mw-userpage-userdoesnotexist error\">\n$1\n</div>",
 1479+ array( 'userpage-userdoesnotexist', wfEscapeWikiText( $username ) ) );
 1480+ } elseif ( $user->isBlocked() ) { # Show log extract if the user is currently blocked
 1481+ LogEventsList::showLogExtract(
 1482+ $wgOut,
 1483+ 'block',
 1484+ $user->getUserPage(),
 1485+ '',
 1486+ array(
 1487+ 'lim' => 1,
 1488+ 'showIfEmpty' => false,
 1489+ 'msgKey' => array(
 1490+ 'blocked-notice-logextract',
 1491+ $user->getName() # Support GENDER in notice
 1492+ )
 1493+ )
 1494+ );
 1495+ }
 1496+ }
 1497+ # Try to add a custom edit intro, or use the standard one if this is not possible.
 1498+ if ( !$this->showCustomIntro() && !$this->mTitle->exists() ) {
 1499+ if ( $wgUser->isLoggedIn() ) {
 1500+ $wgOut->wrapWikiMsg( "<div class=\"mw-newarticletext\">\n$1\n</div>", 'newarticletext' );
 1501+ } else {
 1502+ $wgOut->wrapWikiMsg( "<div class=\"mw-newarticletextanon\">\n$1\n</div>", 'newarticletextanon' );
 1503+ }
 1504+ }
 1505+ # Give a notice if the user is editing a deleted/moved page...
 1506+ if ( !$this->mTitle->exists() ) {
 1507+ LogEventsList::showLogExtract( $wgOut, array( 'delete', 'move' ), $this->mTitle,
 1508+ '', array( 'lim' => 10,
 1509+ 'conds' => array( "log_action != 'revision'" ),
 1510+ 'showIfEmpty' => false,
 1511+ 'msgKey' => array( 'recreate-moveddeleted-warn') )
 1512+ );
 1513+ }
 1514+ }
 1515+
 1516+ /**
 1517+ * Attempt to show a custom editing introduction, if supplied
 1518+ *
 1519+ * @return bool
 1520+ */
 1521+ protected function showCustomIntro() {
 1522+ if ( $this->editintro ) {
 1523+ $title = Title::newFromText( $this->editintro );
 1524+ if ( $title instanceof Title && $title->exists() && $title->userCanRead() ) {
 1525+ global $wgOut;
 1526+ // Added using template syntax, to take <noinclude>'s into account.
 1527+ $wgOut->addWikiTextTitleTidy( '{{:' . $title->getFullText() . '}}', $this->mTitle );
 1528+ return true;
 1529+ } else {
 1530+ return false;
 1531+ }
 1532+ } else {
 1533+ return false;
 1534+ }
 1535+ }
 1536+
 1537+ /**
14361538 * Send the edit form and related headers to $wgOut
14371539 * @param $formCallback Callback that takes an OutputPage parameter; will be called
14381540 * during form output near the top, for captchas and the like.
@@ -1980,6 +2082,36 @@
19812083 }
19822084
19832085 /**
 2086+ * Get a diff between the current contents of the edit box and the
 2087+ * version of the page we're editing from.
 2088+ *
 2089+ * If this is a section edit, we'll replace the section as for final
 2090+ * save and then make a comparison.
 2091+ */
 2092+ function showDiff() {
 2093+ $oldtext = $this->mArticle->fetchContent();
 2094+ $newtext = $this->mArticle->replaceSection(
 2095+ $this->section, $this->textbox1, $this->summary, $this->edittime );
 2096+
 2097+ wfRunHooks( 'EditPageGetDiffText', array( $this, &$newtext ) );
 2098+
 2099+ $newtext = $this->mArticle->preSaveTransform( $newtext );
 2100+ $oldtitle = wfMsgExt( 'currentrev', array( 'parseinline' ) );
 2101+ $newtitle = wfMsgExt( 'yourtext', array( 'parseinline' ) );
 2102+ if ( $oldtext !== false || $newtext != '' ) {
 2103+ $de = new DifferenceEngine( $this->mArticle->getContext() );
 2104+ $de->setText( $oldtext, $newtext );
 2105+ $difftext = $de->getDiff( $oldtitle, $newtitle );
 2106+ $de->showDiffStyle();
 2107+ } else {
 2108+ $difftext = '';
 2109+ }
 2110+
 2111+ global $wgOut;
 2112+ $wgOut->addHTML( '<div id="wikiDiff">' . $difftext . '</div>' );
 2113+ }
 2114+
 2115+ /**
19842116 * Give a chance for site and per-namespace customizations of
19852117 * terms of service summary link that might exist separately
19862118 * from the copyright notice.
@@ -2069,6 +2201,62 @@
20702202 }
20712203 }
20722204
 2205+ /**
 2206+ * @return string
 2207+ */
 2208+ public function getCancelLink() {
 2209+ $cancelParams = array();
 2210+ if ( !$this->isConflict && $this->mArticle->getOldID() > 0 ) {
 2211+ $cancelParams['oldid'] = $this->mArticle->getOldID();
 2212+ }
 2213+
 2214+ return Linker::linkKnown(
 2215+ $this->getContextTitle(),
 2216+ wfMsgExt( 'cancel', array( 'parseinline' ) ),
 2217+ array( 'id' => 'mw-editform-cancel' ),
 2218+ $cancelParams
 2219+ );
 2220+ }
 2221+
 2222+ /**
 2223+ * Returns the URL to use in the form's action attribute.
 2224+ * This is used by EditPage subclasses when simply customizing the action
 2225+ * variable in the constructor is not enough. This can be used when the
 2226+ * EditPage lives inside of a Special page rather than a custom page action.
 2227+ *
 2228+ * @param $title Title object for which is being edited (where we go to for &action= links)
 2229+ * @return string
 2230+ */
 2231+ protected function getActionURL( Title $title ) {
 2232+ return $title->getLocalURL( array( 'action' => $this->action ) );
 2233+ }
 2234+
 2235+ /**
 2236+ * Check if a page was deleted while the user was editing it, before submit.
 2237+ * Note that we rely on the logging table, which hasn't been always there,
 2238+ * but that doesn't matter, because this only applies to brand new
 2239+ * deletes.
 2240+ */
 2241+ protected function wasDeletedSinceLastEdit() {
 2242+ if ( $this->deletedSinceEdit !== null ) {
 2243+ return $this->deletedSinceEdit;
 2244+ }
 2245+
 2246+ $this->deletedSinceEdit = false;
 2247+
 2248+ if ( $this->mTitle->isDeletedQuick() ) {
 2249+ $this->lastDelete = $this->getLastDelete();
 2250+ if ( $this->lastDelete ) {
 2251+ $deleteTime = wfTimestamp( TS_MW, $this->lastDelete->log_timestamp );
 2252+ if ( $deleteTime > $this->starttime ) {
 2253+ $this->deletedSinceEdit = true;
 2254+ }
 2255+ }
 2256+ }
 2257+
 2258+ return $this->deletedSinceEdit;
 2259+ }
 2260+
20732261 protected function getLastDelete() {
20742262 $dbr = wfGetDB( DB_SLAVE );
20752263 $data = $dbr->selectRow(
@@ -2243,177 +2431,6 @@
22442432 }
22452433
22462434 /**
2247 - * Call the stock "user is blocked" page
2248 - *
2249 - * @deprecated in 1.19; throw an exception directly instead
2250 - */
2251 - function blockedPage() {
2252 - global $wgUser;
2253 -
2254 - throw new UserBlockedError( $wgUser->mBlock );
2255 - }
2256 -
2257 - /**
2258 - * Produce the stock "please login to edit pages" page
2259 - *
2260 - * @deprecated in 1.19; throw an exception directly instead
2261 - */
2262 - function userNotLoggedInPage() {
2263 - throw new PermissionsError( 'edit' );
2264 - }
2265 -
2266 - /**
2267 - * Show an error page saying to the user that he has insufficient permissions
2268 - * to create a new page
2269 - *
2270 - * @deprecated in 1.19; throw an exception directly instead
2271 - */
2272 - function noCreatePermission() {
2273 - $permission = $this->mTitle->isTalkPage() ? 'createtalk' : 'createpage';
2274 - throw new PermissionsError( $permission );
2275 - }
2276 -
2277 - /**
2278 - * Creates a basic error page which informs the user that
2279 - * they have attempted to edit a nonexistent section.
2280 - */
2281 - function noSuchSectionPage() {
2282 - global $wgOut;
2283 -
2284 - $wgOut->prepareErrorPage( wfMessage( 'nosuchsectiontitle' ) );
2285 -
2286 - $res = wfMsgExt( 'nosuchsectiontext', 'parse', $this->section );
2287 - wfRunHooks( 'EditPageNoSuchSection', array( &$this, &$res ) );
2288 - $wgOut->addHTML( $res );
2289 -
2290 - $wgOut->returnToMain( false, $this->mTitle );
2291 - }
2292 -
2293 - /**
2294 - * Produce the stock "your edit contains spam" page
2295 - *
2296 - * @param $match Text which triggered one or more filters
2297 - * @deprecated since 1.17 Use method spamPageWithContent() instead
2298 - */
2299 - static function spamPage( $match = false ) {
2300 - global $wgOut, $wgTitle;
2301 -
2302 - $wgOut->prepareErrorPage( wfMessage( 'spamprotectiontitle' ) );
2303 -
2304 - $wgOut->addHTML( '<div id="spamprotected">' );
2305 - $wgOut->addWikiMsg( 'spamprotectiontext' );
2306 - if ( $match ) {
2307 - $wgOut->addWikiMsg( 'spamprotectionmatch', wfEscapeWikiText( $match ) );
2308 - }
2309 - $wgOut->addHTML( '</div>' );
2310 -
2311 - $wgOut->returnToMain( false, $wgTitle );
2312 - }
2313 -
2314 - /**
2315 - * Show "your edit contains spam" page with your diff and text
2316 - *
2317 - * @param $match Text which triggered one or more filters
2318 - */
2319 - public function spamPageWithContent( $match = false ) {
2320 - global $wgOut;
2321 - $this->textbox2 = $this->textbox1;
2322 -
2323 - $wgOut->prepareErrorPage( wfMessage( 'spamprotectiontitle' ) );
2324 -
2325 - $wgOut->addHTML( '<div id="spamprotected">' );
2326 - $wgOut->addWikiMsg( 'spamprotectiontext' );
2327 - if ( $match ) {
2328 - $wgOut->addWikiMsg( 'spamprotectionmatch', wfEscapeWikiText( $match ) );
2329 - }
2330 - $wgOut->addHTML( '</div>' );
2331 -
2332 - $wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourdiff" );
2333 - $de = new DifferenceEngine( $this->mArticle->getContext() );
2334 - $de->setText( $this->getContent(), $this->textbox2 );
2335 - $de->showDiff( wfMsg( "storedversion" ), wfMsgExt( 'yourtext', 'parseinline' ) );
2336 -
2337 - $wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourtext" );
2338 - $this->showTextbox2();
2339 -
2340 - $wgOut->addReturnTo( $this->getContextTitle(), array( 'action' => 'edit' ) );
2341 - }
2342 -
2343 -
2344 - /**
2345 - * @private
2346 - * @todo document
2347 - *
2348 - * @parma $editText string
2349 - *
2350 - * @return bool
2351 - */
2352 - function mergeChangesInto( &$editText ){
2353 - wfProfileIn( __METHOD__ );
2354 -
2355 - $db = wfGetDB( DB_MASTER );
2356 -
2357 - // This is the revision the editor started from
2358 - $baseRevision = $this->getBaseRevision();
2359 - if ( is_null( $baseRevision ) ) {
2360 - wfProfileOut( __METHOD__ );
2361 - return false;
2362 - }
2363 - $baseText = $baseRevision->getText();
2364 -
2365 - // The current state, we want to merge updates into it
2366 - $currentRevision = Revision::loadFromTitle( $db, $this->mTitle );
2367 - if ( is_null( $currentRevision ) ) {
2368 - wfProfileOut( __METHOD__ );
2369 - return false;
2370 - }
2371 - $currentText = $currentRevision->getText();
2372 -
2373 - $result = '';
2374 - if ( wfMerge( $baseText, $editText, $currentText, $result ) ) {
2375 - $editText = $result;
2376 - wfProfileOut( __METHOD__ );
2377 - return true;
2378 - } else {
2379 - wfProfileOut( __METHOD__ );
2380 - return false;
2381 - }
2382 - }
2383 -
2384 - /**
2385 - * Check if the browser is on a blacklist of user-agents known to
2386 - * mangle UTF-8 data on form submission. Returns true if Unicode
2387 - * should make it through, false if it's known to be a problem.
2388 - * @return bool
2389 - * @private
2390 - */
2391 - function checkUnicodeCompliantBrowser() {
2392 - global $wgBrowserBlackList;
2393 - if ( empty( $_SERVER["HTTP_USER_AGENT"] ) ) {
2394 - // No User-Agent header sent? Trust it by default...
2395 - return true;
2396 - }
2397 - $currentbrowser = $_SERVER["HTTP_USER_AGENT"];
2398 - foreach ( $wgBrowserBlackList as $browser ) {
2399 - if ( preg_match($browser, $currentbrowser) ) {
2400 - return false;
2401 - }
2402 - }
2403 - return true;
2404 - }
2405 -
2406 - /**
2407 - * Format an anchor fragment as it would appear for a given section name
2408 - * @param $text String
2409 - * @return String
2410 - * @private
2411 - */
2412 - function sectionAnchor( $text ) {
2413 - global $wgParser;
2414 - return $wgParser->guessSectionNameFromWikiText( $text );
2415 - }
2416 -
2417 - /**
24182435 * Shows a bulletin board style toolbar for common editing functions.
24192436 * It can be disabled in the user preferences.
24202437 * The necessary JavaScript code can be found in skins/common/edit.js.
@@ -2703,53 +2720,136 @@
27042721 }
27052722
27062723 /**
2707 - * @return string
 2724+ * Call the stock "user is blocked" page
 2725+ *
 2726+ * @deprecated in 1.19; throw an exception directly instead
27082727 */
2709 - public function getCancelLink() {
2710 - $cancelParams = array();
2711 - if ( !$this->isConflict && $this->mArticle->getOldID() > 0 ) {
2712 - $cancelParams['oldid'] = $this->mArticle->getOldID();
2713 - }
 2728+ function blockedPage() {
 2729+ global $wgUser;
27142730
2715 - return Linker::linkKnown(
2716 - $this->getContextTitle(),
2717 - wfMsgExt( 'cancel', array( 'parseinline' ) ),
2718 - array( 'id' => 'mw-editform-cancel' ),
2719 - $cancelParams
2720 - );
 2731+ throw new UserBlockedError( $wgUser->mBlock );
27212732 }
27222733
27232734 /**
2724 - * Get a diff between the current contents of the edit box and the
2725 - * version of the page we're editing from.
 2735+ * Produce the stock "please login to edit pages" page
27262736 *
2727 - * If this is a section edit, we'll replace the section as for final
2728 - * save and then make a comparison.
 2737+ * @deprecated in 1.19; throw an exception directly instead
27292738 */
2730 - function showDiff() {
2731 - $oldtext = $this->mArticle->fetchContent();
2732 - $newtext = $this->mArticle->replaceSection(
2733 - $this->section, $this->textbox1, $this->summary, $this->edittime );
 2739+ function userNotLoggedInPage() {
 2740+ throw new PermissionsError( 'edit' );
 2741+ }
27342742
2735 - wfRunHooks( 'EditPageGetDiffText', array( $this, &$newtext ) );
 2743+ /**
 2744+ * Show an error page saying to the user that he has insufficient permissions
 2745+ * to create a new page
 2746+ *
 2747+ * @deprecated in 1.19; throw an exception directly instead
 2748+ */
 2749+ function noCreatePermission() {
 2750+ $permission = $this->mTitle->isTalkPage() ? 'createtalk' : 'createpage';
 2751+ throw new PermissionsError( $permission );
 2752+ }
27362753
2737 - $newtext = $this->mArticle->preSaveTransform( $newtext );
2738 - $oldtitle = wfMsgExt( 'currentrev', array( 'parseinline' ) );
2739 - $newtitle = wfMsgExt( 'yourtext', array( 'parseinline' ) );
2740 - if ( $oldtext !== false || $newtext != '' ) {
2741 - $de = new DifferenceEngine( $this->mArticle->getContext() );
2742 - $de->setText( $oldtext, $newtext );
2743 - $difftext = $de->getDiff( $oldtitle, $newtitle );
2744 - $de->showDiffStyle();
2745 - } else {
2746 - $difftext = '';
 2754+ /**
 2755+ * Creates a basic error page which informs the user that
 2756+ * they have attempted to edit a nonexistent section.
 2757+ */
 2758+ function noSuchSectionPage() {
 2759+ global $wgOut;
 2760+
 2761+ $wgOut->prepareErrorPage( wfMessage( 'nosuchsectiontitle' ) );
 2762+
 2763+ $res = wfMsgExt( 'nosuchsectiontext', 'parse', $this->section );
 2764+ wfRunHooks( 'EditPageNoSuchSection', array( &$this, &$res ) );
 2765+ $wgOut->addHTML( $res );
 2766+
 2767+ $wgOut->returnToMain( false, $this->mTitle );
 2768+ }
 2769+
 2770+ /**
 2771+ * Produce the stock "your edit contains spam" page
 2772+ *
 2773+ * @param $match Text which triggered one or more filters
 2774+ * @deprecated since 1.17 Use method spamPageWithContent() instead
 2775+ */
 2776+ static function spamPage( $match = false ) {
 2777+ global $wgOut, $wgTitle;
 2778+
 2779+ $wgOut->prepareErrorPage( wfMessage( 'spamprotectiontitle' ) );
 2780+
 2781+ $wgOut->addHTML( '<div id="spamprotected">' );
 2782+ $wgOut->addWikiMsg( 'spamprotectiontext' );
 2783+ if ( $match ) {
 2784+ $wgOut->addWikiMsg( 'spamprotectionmatch', wfEscapeWikiText( $match ) );
27472785 }
 2786+ $wgOut->addHTML( '</div>' );
27482787
 2788+ $wgOut->returnToMain( false, $wgTitle );
 2789+ }
 2790+
 2791+ /**
 2792+ * Show "your edit contains spam" page with your diff and text
 2793+ *
 2794+ * @param $match Text which triggered one or more filters
 2795+ */
 2796+ public function spamPageWithContent( $match = false ) {
27492797 global $wgOut;
2750 - $wgOut->addHTML( '<div id="wikiDiff">' . $difftext . '</div>' );
 2798+ $this->textbox2 = $this->textbox1;
 2799+
 2800+ $wgOut->prepareErrorPage( wfMessage( 'spamprotectiontitle' ) );
 2801+
 2802+ $wgOut->addHTML( '<div id="spamprotected">' );
 2803+ $wgOut->addWikiMsg( 'spamprotectiontext' );
 2804+ if ( $match ) {
 2805+ $wgOut->addWikiMsg( 'spamprotectionmatch', wfEscapeWikiText( $match ) );
 2806+ }
 2807+ $wgOut->addHTML( '</div>' );
 2808+
 2809+ $wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourdiff" );
 2810+ $de = new DifferenceEngine( $this->mArticle->getContext() );
 2811+ $de->setText( $this->getContent(), $this->textbox2 );
 2812+ $de->showDiff( wfMsg( "storedversion" ), wfMsgExt( 'yourtext', 'parseinline' ) );
 2813+
 2814+ $wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourtext" );
 2815+ $this->showTextbox2();
 2816+
 2817+ $wgOut->addReturnTo( $this->getContextTitle(), array( 'action' => 'edit' ) );
27512818 }
27522819
27532820 /**
 2821+ * Format an anchor fragment as it would appear for a given section name
 2822+ * @param $text String
 2823+ * @return String
 2824+ * @private
 2825+ */
 2826+ function sectionAnchor( $text ) {
 2827+ global $wgParser;
 2828+ return $wgParser->guessSectionNameFromWikiText( $text );
 2829+ }
 2830+
 2831+ /**
 2832+ * Check if the browser is on a blacklist of user-agents known to
 2833+ * mangle UTF-8 data on form submission. Returns true if Unicode
 2834+ * should make it through, false if it's known to be a problem.
 2835+ * @return bool
 2836+ * @private
 2837+ */
 2838+ function checkUnicodeCompliantBrowser() {
 2839+ global $wgBrowserBlackList;
 2840+ if ( empty( $_SERVER["HTTP_USER_AGENT"] ) ) {
 2841+ // No User-Agent header sent? Trust it by default...
 2842+ return true;
 2843+ }
 2844+ $currentbrowser = $_SERVER["HTTP_USER_AGENT"];
 2845+ foreach ( $wgBrowserBlackList as $browser ) {
 2846+ if ( preg_match($browser, $currentbrowser) ) {
 2847+ return false;
 2848+ }
 2849+ }
 2850+ return true;
 2851+ }
 2852+
 2853+ /**
27542854 * Filter an input field through a Unicode de-armoring process if it
27552855 * came from an old browser with known broken Unicode editing issues.
27562856 *
@@ -2875,105 +2975,4 @@
28762976 // reverse the transform that we made for reversability reasons.
28772977 return strtr( $result, array( "&#x0" => "&#x" ) );
28782978 }
2879 -
2880 - /**
2881 - * Attempt submission
2882 - * @return bool false if output is done, true if the rest of the form should be displayed
2883 - */
2884 - function attemptSave() {
2885 - global $wgUser, $wgOut;
2886 -
2887 - $resultDetails = false;
2888 - # Allow bots to exempt some edits from bot flagging
2889 - $bot = $wgUser->isAllowed( 'bot' ) && $this->bot;
2890 - $status = $this->internalAttemptSave( $resultDetails, $bot );
2891 - // FIXME: once the interface for internalAttemptSave() is made nicer, this should use the message in $status
2892 -
2893 - if ( $status->value == self::AS_SUCCESS_UPDATE || $status->value == self::AS_SUCCESS_NEW_ARTICLE ) {
2894 - $this->didSave = true;
2895 - }
2896 -
2897 - switch ( $status->value ) {
2898 - case self::AS_HOOK_ERROR_EXPECTED:
2899 - case self::AS_CONTENT_TOO_BIG:
2900 - case self::AS_ARTICLE_WAS_DELETED:
2901 - case self::AS_CONFLICT_DETECTED:
2902 - case self::AS_SUMMARY_NEEDED:
2903 - case self::AS_TEXTBOX_EMPTY:
2904 - case self::AS_MAX_ARTICLE_SIZE_EXCEEDED:
2905 - case self::AS_END:
2906 - return true;
2907 -
2908 - case self::AS_HOOK_ERROR:
2909 - case self::AS_FILTERING:
2910 - return false;
2911 -
2912 - case self::AS_SUCCESS_NEW_ARTICLE:
2913 - $query = $resultDetails['redirect'] ? 'redirect=no' : '';
2914 - $wgOut->redirect( $this->mTitle->getFullURL( $query ) );
2915 - return false;
2916 -
2917 - case self::AS_SUCCESS_UPDATE:
2918 - $extraQuery = '';
2919 - $sectionanchor = $resultDetails['sectionanchor'];
2920 -
2921 - // Give extensions a chance to modify URL query on update
2922 - wfRunHooks( 'ArticleUpdateBeforeRedirect', array( $this->mArticle, &$sectionanchor, &$extraQuery ) );
2923 -
2924 - if ( $resultDetails['redirect'] ) {
2925 - if ( $extraQuery == '' ) {
2926 - $extraQuery = 'redirect=no';
2927 - } else {
2928 - $extraQuery = 'redirect=no&' . $extraQuery;
2929 - }
2930 - }
2931 - $wgOut->redirect( $this->mTitle->getFullURL( $extraQuery ) . $sectionanchor );
2932 - return false;
2933 -
2934 - case self::AS_BLANK_ARTICLE:
2935 - $wgOut->redirect( $this->getContextTitle()->getFullURL() );
2936 - return false;
2937 -
2938 - case self::AS_SPAM_ERROR:
2939 - $this->spamPageWithContent( $resultDetails['spam'] );
2940 - return false;
2941 -
2942 - case self::AS_BLOCKED_PAGE_FOR_USER:
2943 - throw new UserBlockedError( $wgUser->mBlock );
2944 -
2945 - case self::AS_IMAGE_REDIRECT_ANON:
2946 - case self::AS_IMAGE_REDIRECT_LOGGED:
2947 - throw new PermissionsError( 'upload' );
2948 -
2949 - case self::AS_READ_ONLY_PAGE_ANON:
2950 - case self::AS_READ_ONLY_PAGE_LOGGED:
2951 - throw new PermissionsError( 'edit' );
2952 -
2953 - case self::AS_READ_ONLY_PAGE:
2954 - throw new ReadOnlyError;
2955 -
2956 - case self::AS_RATE_LIMITED:
2957 - throw new ThrottledError();
2958 -
2959 - case self::AS_NO_CREATE_PERMISSION:
2960 - $permission = $this->mTitle->isTalkPage() ? 'createtalk' : 'createpage';
2961 - throw new PermissionsError( $permission );
2962 -
2963 - }
2964 - return false;
2965 - }
2966 -
2967 - /**
2968 - * @return Revision
2969 - */
2970 - function getBaseRevision() {
2971 - if ( !$this->mBaseRevision ) {
2972 - $db = wfGetDB( DB_MASTER );
2973 - $baseRevision = Revision::loadFromTimestamp(
2974 - $db, $this->mTitle, $this->edittime );
2975 - return $this->mBaseRevision = $baseRevision;
2976 - } else {
2977 - return $this->mBaseRevision;
2978 - }
2979 - }
29802979 }

Status & tagging log