* (bug 41267) mediawiki.action.edit.preview is not loaded
[lhc/web/wiklou.git] / includes / EditPage.php
index a1a2686..15321fc 100644 (file)
@@ -219,7 +219,7 @@ class EditPage {
        var $textbox1 = '', $textbox2 = '', $summary = '', $nosummary = false;
        var $edittime = '', $section = '', $sectiontitle = '', $starttime = '';
        var $oldid = 0, $editintro = '', $scrolltop = null, $bot = true;
-       var $content_model = null, $content_format = null;
+       var $contentModel = null, $contentFormat = null;
 
        # Placeholders for text injection by hooks (must be HTML)
        # extensions should take care to _append_ to the present value
@@ -253,10 +253,10 @@ class EditPage {
                $this->mArticle = $article;
                $this->mTitle = $article->getTitle();
 
-               $this->content_model = $this->mTitle->getContentModel();
+               $this->contentModel = $this->mTitle->getContentModel();
 
-               $handler = ContentHandler::getForModelID( $this->content_model );
-               $this->content_format = $handler->getDefaultFormat(); #NOTE: should be overridden by format of actual revision
+               $handler = ContentHandler::getForModelID( $this->contentModel );
+               $this->contentFormat = $handler->getDefaultFormat();
        }
 
        /**
@@ -285,7 +285,7 @@ class EditPage {
 
        /**
         * Get the context title object.
-        * If not set, $wgTitle will be returned. This behavior might changed in
+        * If not set, $wgTitle will be returned. This behavior might change in
         * the future to return $this->mTitle instead.
         *
         * @return Title object
@@ -381,7 +381,6 @@ class EditPage {
                $this->isCssSubpage         = $this->mTitle->isCssSubpage();
                $this->isJsSubpage          = $this->mTitle->isJsSubpage();
                $this->isWrongCaseCssJsPage = $this->isWrongCaseCssJsPage();
-               $this->isNew                = !$this->mTitle->exists() || $this->section == 'new';
 
                # Show applicable editing introductions
                if ( $this->formtype == 'initial' || $this->firsttime ) {
@@ -410,14 +409,10 @@ class EditPage {
                                wfProfileOut( __METHOD__ );
                                return;
                        }
-
-                       if ( !$this->mTitle->getArticleID() ) {
+                       if ( !$this->mTitle->getArticleID() )
                                wfRunHooks( 'EditFormPreloadText', array( &$this->textbox1, &$this->mTitle ) );
-                       }
-                       else {
+                       else
                                wfRunHooks( 'EditFormInitialText', array( $this ) );
-                       }
-
                }
 
                $this->showEditForm();
@@ -460,6 +455,7 @@ class EditPage {
         * @since 1.19
         * @param $permErrors Array of permissions errors, as returned by
         *                    Title::getUserPermissionsErrors().
+        * @throws PermissionsError
         */
        protected function displayPermissionsError( array $permErrors ) {
                global $wgRequest, $wgOut;
@@ -475,7 +471,7 @@ class EditPage {
                $content = $this->getContentObject();
 
                # Use the normal message if there's nothing to display
-               if ( $this->firsttime && $content->isEmpty() ) {
+               if ( $this->firsttime && ( !$content || $content->isEmpty() ) ) {
                        $action = $this->mTitle->exists() ? 'edit' :
                                ( $this->mTitle->isTalkPage() ? 'createtalk' : 'createpage' );
                        throw new PermissionsError( $action, $permErrors );
@@ -591,12 +587,13 @@ class EditPage {
         * @param $request WebRequest
         */
        function importFormData( &$request ) {
-               global $wgLang, $wgUser;
+               global $wgContLang, $wgUser;
 
                wfProfileIn( __METHOD__ );
 
                # Section edit can come from either the form or a link
                $this->section = $request->getVal( 'wpSection', $request->getVal( 'section' ) );
+               $this->isNew = !$this->mTitle->exists() || $this->section == 'new';
 
                if ( $request->wasPosted() ) {
                        # These fields need to be checked for encoding.
@@ -609,15 +606,13 @@ class EditPage {
                                // modified by subclasses
                                wfProfileIn( get_class( $this ) . "::importContentFormData" );
                                $textbox1 = $this->importContentFormData( $request );
-                               if ( isset( $textbox1 ) ) {
+                               if ( isset( $textbox1 ) )
                                        $this->textbox1 = $textbox1;
-                               }
-
                                wfProfileOut( get_class( $this ) . "::importContentFormData" );
                        }
 
                        # Truncate for whole multibyte characters
-                       $this->summary = $wgLang->truncate( $request->getText( 'wpSummary' ), 255 );
+                       $this->summary = $wgContLang->truncate( $request->getText( 'wpSummary' ), 255 );
 
                        # If the summary consists of a heading, e.g. '==Foobar==', extract the title from the
                        # header syntax, e.g. 'Foobar'. This is mainly an issue when we are using wpSummary for
@@ -629,7 +624,7 @@ class EditPage {
                        # currently doing double duty as both edit summary and section title. Right now this
                        # is just to allow API edits to work around this limitation, but this should be
                        # incorporated into the actual edit form when EditPage is rewritten (Bugs 18654, 26312).
-                       $this->sectiontitle = $wgLang->truncate( $request->getText( 'wpSectionTitle' ), 255 );
+                       $this->sectiontitle = $wgContLang->truncate( $request->getText( 'wpSectionTitle' ), 255 );
                        $this->sectiontitle = preg_replace( '/^\s*=+\s*(.*?)\s*=+\s*$/', '$1', $this->sectiontitle );
 
                        $this->edittime = $request->getVal( 'wpEdittime' );
@@ -742,8 +737,8 @@ class EditPage {
                $this->nosummary = $request->getBool( 'nosummary' );
 
                $content_handler = ContentHandler::getForTitle( $this->mTitle );
-               $this->content_model = $request->getText( 'model', $content_handler->getModelID() ); #may be overridden by revision
-               $this->content_format = $request->getText( 'format', $content_handler->getDefaultFormat() ); #may be overridden by revision
+               $this->contentModel = $request->getText( 'model', $content_handler->getModelID() ); #may be overridden by revision
+               $this->contentFormat = $request->getText( 'format', $content_handler->getDefaultFormat() ); #may be overridden by revision
 
                #TODO: check if the desired model is allowed in this namespace, and if a transition from the page's current model to the new model is allowed
                #TODO: check if the desired content model supports the given content format!
@@ -781,6 +776,9 @@ class EditPage {
                $this->edittime = $this->mArticle->getTimestamp();
 
                $content = $this->getContentObject( false ); #TODO: track content object?!
+               if ( $content === false ) {
+                       return false;
+               }
                $this->textbox1 = $this->toEditText( $content );
 
                // activate checkboxes if user wants them to be always active
@@ -808,14 +806,13 @@ class EditPage {
        /**
         * Fetch initial editing page content.
         *
-        * @param $def_text string
+        * @param $def_text string|bool
         * @return mixed string on success, $def_text for invalid sections
         * @private
-        * @deprecated since 1.21
-        * @todo: deprecated, replace usage everywhere
+        * @deprecated since 1.21, get WikiPage::getContent() instead.
         */
        function getContent( $def_text = false ) {
-               wfDeprecated( __METHOD__, '1.21' );
+               ContentHandler::deprecated( __METHOD__, '1.21' );
 
                if ( $def_text !== null && $def_text !== false && $def_text !== '' ) {
                        $def_content = $this->toEditContent( $def_text );
@@ -829,7 +826,14 @@ class EditPage {
                return $this->toEditText( $content );
        }
 
-       private function getContentObject( $def_content = null ) {
+       /**
+        * @param Content|null $def_content The default value to return
+        *
+        * @return mixed Content on success, $def_content for invalid sections
+        *
+        * @since 1.21
+        */
+       protected function getContentObject( $def_content = null ) {
                global $wgOut, $wgRequest;
 
                wfProfileIn( __METHOD__ );
@@ -936,11 +940,11 @@ class EditPage {
         * to the original text of the edit.
         *
         * This difers from Article::getContent() that when a missing revision is
-        * encountered the result will be an empty string and not the
+        * encountered the result will be null and not the
         * 'missing-revision' message.
         *
         * @since 1.19
-        * @return string
+        * @return Content|null
         */
        private function getOriginalContent() {
                if ( $this->section == 'new' ) {
@@ -948,8 +952,8 @@ class EditPage {
                }
                $revision = $this->mArticle->getRevisionFetched();
                if ( $revision === null ) {
-                       if ( !$this->content_model ) $this->content_model = $this->getTitle()->getContentModel();
-                       $handler = ContentHandler::getForModelID( $this->content_model );
+                       if ( !$this->contentModel ) $this->contentModel = $this->getTitle()->getContentModel();
+                       $handler = ContentHandler::getForModelID( $this->contentModel );
 
                        return $handler->makeEmptyContent();
                }
@@ -963,21 +967,21 @@ class EditPage {
         * content object is returned instead of null.
         *
         * @since 1.21
-        * @return string
+        * @return Content
         */
-       private function getCurrentContent() {
+       protected function getCurrentContent() {
                $rev = $this->mArticle->getRevision();
                $content = $rev ? $rev->getContent( Revision::RAW ) : null;
 
                if ( $content  === false || $content === null ) {
-                       if ( !$this->content_model ) $this->content_model = $this->getTitle()->getContentModel();
-                       $handler = ContentHandler::getForModelID( $this->content_model );
+                       if ( !$this->contentModel ) $this->contentModel = $this->getTitle()->getContentModel();
+                       $handler = ContentHandler::getForModelID( $this->contentModel );
 
                        return $handler->makeEmptyContent();
                } else {
                        # nasty side-effect, but needed for consistency
-                       $this->content_model = $rev->getContentModel();
-                       $this->content_format = $rev->getContentFormat();
+                       $this->contentModel = $rev->getContentModel();
+                       $this->contentFormat = $rev->getContentFormat();
 
                        return $content;
                }
@@ -988,10 +992,10 @@ class EditPage {
         * Use this method before edit() to preload some text into the edit box
         *
         * @param $text string
-        * @deprecated since 1.21
+        * @deprecated since 1.21, use setPreloadedContent() instead.
         */
        public function setPreloadedText( $text ) {
-               wfDeprecated( __METHOD__, "1.21" );
+               ContentHandler::deprecated( __METHOD__, "1.21" );
 
                $content = $this->toEditContent( $text );
 
@@ -1006,7 +1010,7 @@ class EditPage {
         * @since 1.21
         */
        public function setPreloadedContent( Content $content ) {
-               $this->mPreloadedContent = $content;
+               $this->mPreloadContent = $content;
        }
 
        /**
@@ -1019,8 +1023,8 @@ class EditPage {
         *
         * @deprecated since 1.21, use getPreloadedContent() instead
         */
-       protected function getPreloadedText( $preload ) { #NOTE: B/C only, replace usage!
-               wfDeprecated( __METHOD__, "1.21" );
+       protected function getPreloadedText( $preload ) {
+               ContentHandler::deprecated( __METHOD__, "1.21" );
 
                $content = $this->getPreloadedContent( $preload );
                $text = $this->toEditText( $content );
@@ -1038,7 +1042,7 @@ class EditPage {
         *
         * @since 1.21
         */
-       protected function getPreloadedContent( $preload ) { #@todo: use this!
+       protected function getPreloadedContent( $preload ) {
                global $wgUser;
 
                if ( !empty( $this->mPreloadContent ) ) {
@@ -1053,7 +1057,7 @@ class EditPage {
 
                $title = Title::newFromText( $preload );
                # Check for existence to avoid getting MediaWiki:Noarticletext
-               if ( $title === null || !$title->exists() || !$title->userCan( 'read', $wgUser ) ) {
+               if ( $title === null || !$title->exists() || !$title->userCan( 'read' ) ) {
                        return $handler->makeEmptyContent();
                }
 
@@ -1061,7 +1065,7 @@ class EditPage {
                if ( $page->isRedirect() ) {
                        $title = $page->getRedirectTarget();
                        # Same as before
-                       if ( $title === null || !$title->exists() || !$title->userCan( 'read', $wgUser ) ) {
+                       if ( $title === null || !$title->exists() || !$title->userCan( 'read' ) ) {
                                return $handler->makeEmptyContent();
                        }
                        $page = WikiPage::factory( $title );
@@ -1070,6 +1074,10 @@ class EditPage {
                $parserOptions = ParserOptions::newFromUser( $wgUser );
                $content = $page->getContent( Revision::RAW );
 
+               if ( !$content ) {
+                       return $handler->makeEmptyContent();
+               }
+
                return $content->preloadTransform( $title, $parserOptions );
        }
 
@@ -1090,6 +1098,7 @@ class EditPage {
 
        /**
         * Attempt submission
+        * @throws UserBlockedError|ReadOnlyError|ThrottledError|PermissionsError
         * @return bool false if output is done, true if the rest of the form should be displayed
         */
        function attemptSave() {
@@ -1218,7 +1227,7 @@ class EditPage {
                        # Construct Content object
                        $textbox_content = $this->toEditContent( $this->textbox1 );
                } catch (MWContentSerializationException $ex) {
-                       $status->fatal( 'content-failed-to-parse', $this->content_model, $this->content_format, $ex->getMessage() );
+                       $status->fatal( 'content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage() );
                        $status->value = self::AS_PARSE_ERROR;
                        wfProfileOut( __METHOD__ );
                        return $status;
@@ -1338,7 +1347,7 @@ class EditPage {
 
                if ( $new ) {
                        // Late check for create permission, just in case *PARANOIA*
-                       if ( !$this->mTitle->userCan( 'create', $wgUser ) ) {
+                       if ( !$this->mTitle->userCan( 'create' ) ) {
                                $status->fatal( 'nocreatetext' );
                                $status->value = self::AS_NO_CREATE_PERMISSION;
                                wfDebug( __METHOD__ . ": no create permission\n" );
@@ -1384,8 +1393,8 @@ class EditPage {
                                        // passed.
                                        if ( $this->summary === '' ) {
                                                $cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle );
-                                               $this->summary = wfMessage( 'newsectionsummary' )
-                                                       ->rawParams( $cleanSectionTitle )->inContentLanguage()->text() ;
+                                               $this->summary = wfMessage( 'newsectionsummary', $cleanSectionTitle )
+                                                       ->inContentLanguage()->text() ;
                                        }
                                } elseif ( $this->summary !== '' ) {
                                        // Insert the section title above the content.
@@ -1396,8 +1405,8 @@ class EditPage {
 
                                        // Create a link to the new section from the edit summary.
                                        $cleanSummary = $wgParser->stripSectionName( $this->summary );
-                                       $this->summary = wfMessage( 'newsectionsummary' )
-                                               ->rawParams( $cleanSummary )->inContentLanguage()->text();
+                                       $this->summary = wfMessage( 'newsectionsummary', $cleanSummary )
+                                               ->inContentLanguage()->text();
                                }
                        }
 
@@ -1426,7 +1435,8 @@ class EditPage {
                                                $this->isConflict = false;
                                                wfDebug( __METHOD__ . ": conflict suppressed; new section\n" );
                                        }
-                               } elseif ( $this->section == '' && Revision::userWasLastToEdit( DB_MASTER,  $this->mTitle->getArticleID(), $wgUser->getId(), $this->edittime ) ) {
+                               } elseif ( $this->section == '' && Revision::userWasLastToEdit( DB_MASTER,  $this->mTitle->getArticleID(),
+                                                       $wgUser->getId(), $this->edittime ) ) {
                                        # Suppress edit conflict with self, except for section edits where merging is required.
                                        wfDebug( __METHOD__ . ": Suppressing edit conflict, same user.\n" );
                                        $this->isConflict = false;
@@ -1447,8 +1457,7 @@ class EditPage {
                                wfDebug( __METHOD__ . ": conflict! getting section '{$this->section}' for time '{$this->edittime}'"
                                                . " (article time '{$timestamp}')\n" );
 
-                               $content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content,
-                                                                                                                                       $sectionTitle, $this->edittime );
+                               $content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content, $sectionTitle, $this->edittime );
                        } else {
                                wfDebug( __METHOD__ . ": getting section '{$this->section}'\n" );
                                $content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content, $sectionTitle );
@@ -1540,16 +1549,16 @@ class EditPage {
                                        // passed.
                                        if ( $this->summary === '' ) {
                                                $cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle );
-                                               $this->summary = wfMessage( 'newsectionsummary' )
-                                                       ->rawParams( $cleanSectionTitle )->inContentLanguage()->text();
+                                               $this->summary = wfMessage( 'newsectionsummary', $cleanSectionTitle )
+                                                       ->inContentLanguage()->text();
                                        }
                                } elseif ( $this->summary !== '' ) {
                                        $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->summary );
                                        # This is a new section, so create a link to the new section
                                        # in the revision summary.
                                        $cleanSummary = $wgParser->stripSectionName( $this->summary );
-                                       $this->summary = wfMessage( 'newsectionsummary' )
-                                               ->rawParams( $cleanSummary )->inContentLanguage()->text();
+                                       $this->summary = wfMessage( 'newsectionsummary', $cleanSummary )
+                                               ->inContentLanguage()->text();
                                }
                        } elseif ( $this->section != '' ) {
                                # Try to get a section anchor from the section source, redirect to edited section if header found
@@ -1590,11 +1599,11 @@ class EditPage {
                        ( $bot ? EDIT_FORCE_BOT : 0 );
 
                        $doEditStatus = $this->mArticle->doEditContent( $content, $this->summary, $flags,
-                                                                                                                       false, null, $this->content_format );
+                                                                                                                       false, null, $this->contentFormat );
 
                if ( $doEditStatus->isOK() ) {
-                       $result['redirect'] = $content->isRedirect();
-                       $this->updateWatchlist();
+                               $result['redirect'] = $content->isRedirect();
+                       $this->commitWatch();
                        wfProfileOut( __METHOD__ );
                        return $status;
                } else {
@@ -1615,27 +1624,19 @@ class EditPage {
        }
 
        /**
-        * Register the change of watch status
+        * Commit the change of watch status
         */
-       protected function updateWatchlist() {
+       protected function commitWatch() {
                global $wgUser;
-
                if ( $wgUser->isLoggedIn() && $this->watchthis != $wgUser->isWatched( $this->mTitle ) ) {
-                       $fname = __METHOD__;
-                       $title = $this->mTitle;
-                       $watch = $this->watchthis;
-
-                       // Do this in its own transaction to reduce contention...
                        $dbw = wfGetDB( DB_MASTER );
-                       $dbw->onTransactionIdle( function() use ( $dbw, $title, $watch, $wgUser, $fname ) {
-                               $dbw->begin( $fname );
-                               if ( $watch ) {
-                                       WatchAction::doWatch( $title, $wgUser );
-                               } else {
-                                       WatchAction::doUnwatch( $title, $wgUser );
-                               }
-                               $dbw->commit( $fname );
-                       } );
+                       $dbw->begin( __METHOD__ );
+                       if ( $this->watchthis ) {
+                               WatchAction::doWatch( $this->mTitle, $wgUser );
+                       } else {
+                               WatchAction::doUnwatch( $this->mTitle, $wgUser );
+                       }
+                       $dbw->commit( __METHOD__ );
                }
        }
 
@@ -1649,7 +1650,7 @@ class EditPage {
         * @deprecated since 1.21, use mergeChangesIntoContent() instead
         */
        function mergeChangesInto( &$editText ){
-               wfDebug( __METHOD__, "1.21" );
+               ContentHandler::deprecated( __METHOD__, "1.21" );
 
                $editContent = $this->toEditContent( $editText );
 
@@ -1658,19 +1659,17 @@ class EditPage {
                if ( $ok ) {
                        $editText = $this->toEditText( $editContent );
                        return true;
-               } else {
-                       return false;
                }
+               return false;
        }
 
        /**
         * @private
         * @todo document
         *
-        * @parma $editText string
-        *
+        * @param $editContent
         * @return bool
-        * @since since 1.21
+        * @since since 1.WD
         */
        private function mergeChangesIntoContent( &$editContent ){
                wfProfileIn( __METHOD__ );
@@ -1679,19 +1678,21 @@ class EditPage {
 
                // This is the revision the editor started from
                $baseRevision = $this->getBaseRevision();
-               if ( is_null( $baseRevision ) ) {
+               $baseContent = $baseRevision ? $baseRevision->getContent() : null;
+
+               if ( is_null( $baseContent ) ) {
                        wfProfileOut( __METHOD__ );
                        return false;
                }
-               $baseContent = $baseRevision->getContent();
 
                // The current state, we want to merge updates into it
                $currentRevision = Revision::loadFromTitle( $db, $this->mTitle );
-               if ( is_null( $currentRevision ) ) {
+               $currentContent = $currentRevision ? $currentRevision->getContent() : null;
+
+               if ( is_null( $currentContent ) ) {
                        wfProfileOut( __METHOD__ );
                        return false;
                }
-               $currentContent = $currentRevision->getContent();
 
                $handler = ContentHandler::getForModelID( $baseContent->getModel() );
 
@@ -1868,10 +1869,13 @@ class EditPage {
                # Give a notice if the user is editing a deleted/moved page...
                if ( !$this->mTitle->exists() ) {
                        LogEventsList::showLogExtract( $wgOut, array( 'delete', 'move' ), $this->mTitle,
-                               '', array( 'lim' => 10,
-                                          'conds' => array( "log_action != 'revision'" ),
-                                          'showIfEmpty' => false,
-                                          'msgKey' => array( 'recreate-moveddeleted-warn' ) )
+                               '',
+                               array(
+                                       'lim' => 10,
+                                       'conds' => array( "log_action != 'revision'" ),
+                                       'showIfEmpty' => false,
+                                       'msgKey' => array( 'recreate-moveddeleted-warn' )
+                               )
                        );
                }
        }
@@ -1889,35 +1893,42 @@ class EditPage {
                                // Added using template syntax, to take <noinclude>'s into account.
                                $wgOut->addWikiTextTitleTidy( '{{:' . $title->getFullText() . '}}', $this->mTitle );
                                return true;
-                       } else {
-                               return false;
                        }
-               } else {
-                       return false;
                }
+               return false;
        }
 
        /**
-        * Gets an editable textual representation of the given Content object.
+        * Gets an editable textual representation of $content.
         * The textual representation can be turned by into a Content object by the
         * toEditContent() method.
         *
+        * If $content is null or false or a string, $content is returned unchanged.
+        *
         * If the given Content object is not of a type that can be edited using the text base EditPage,
         * an exception will be raised. Set $this->allowNonTextContent to true to allow editing of non-textual
         * content.
         *
-        * @param Content $content
+        * @param Content|null|false|string $content
         * @return String the editable text form of the content.
         *
         * @throws MWException if $content is not an instance of TextContent and $this->allowNonTextContent is not true.
         */
-       protected function toEditText( Content $content ) {
+       protected function toEditText( $content ) {
+               if ( $content === null || $content === false ) {
+                       return $content;
+               }
+
+               if ( is_string( $content ) ) {
+                       return $content;
+               }
+
                if ( !$this->allowNonTextContent && !( $content instanceof TextContent ) ) {
                        throw new MWException( "This content model can not be edited as text: "
                                                                . ContentHandler::getLocalizedName( $content->getModel() ) );
                }
 
-               return $content->serialize( $this->content_format );
+               return $content->serialize( $this->contentFormat );
        }
 
        /**
@@ -1927,15 +1938,20 @@ class EditPage {
         * an exception will be raised. Set $this->allowNonTextContent to true to allow editing of non-textual
         * content.
         *
-        * @param String $text Text to unserialize
-        * @return Content the content object created from $text
+        * @param String|null|bool $text Text to unserialize
+        * @return Content The content object created from $text. If $text was false or null, false resp. null will be
+        *                 returned instead.
         *
         * @throws MWException if unserializing the text results in a Content object that is not an instance of TextContent
         *          and $this->allowNonTextContent is not true.
         */
        protected function toEditContent( $text ) {
+               if ( $text === false || $text === null ) {
+                       return $text;
+               }
+
                $content = ContentHandler::makeContent( $text, $this->getTitle(),
-                       $this->content_model, $this->content_format );
+                       $this->contentModel, $this->contentFormat );
 
                if ( !$this->allowNonTextContent && !( $content instanceof TextContent ) ) {
                        throw new MWException( "This content model can not be edited as text: "
@@ -1947,7 +1963,7 @@ class EditPage {
 
        /**
         * Send the edit form and related headers to $wgOut
-        * @param $formCallback Callback that takes an OutputPage parameter; will be called
+        * @param $formCallback Callback|null that takes an OutputPage parameter; will be called
         *     during form output near the top, for captchas and the like.
         */
        function showEditForm( $formCallback = null ) {
@@ -2059,8 +2075,8 @@ class EditPage {
 
                $wgOut->addHTML( Html::hidden( 'oldid', $this->oldid ) );
 
-               $wgOut->addHTML( Html::hidden( 'format', $this->content_format ) );
-               $wgOut->addHTML( Html::hidden( 'model', $this->content_model ) );
+               $wgOut->addHTML( Html::hidden( 'format', $this->contentFormat ) );
+               $wgOut->addHTML( Html::hidden( 'model', $this->contentModel ) );
 
                if ( $this->section == 'new' ) {
                        $this->showSummaryInput( true, $this->summary );
@@ -2111,7 +2127,7 @@ class EditPage {
                                $this->showConflict();
                        } catch ( MWContentSerializationException $ex ) {
                                // this can't really happen, but be nice if it does.
-                               $msg = wfMessage( 'content-failed-to-parse', $this->content_model, $this->content_format, $ex->getMessage() );
+                               $msg = wfMessage( 'content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage() );
                                $wgOut->addWikiText( '<div class="error">' . $msg->text() . '</div>');
                        }
                }
@@ -2219,7 +2235,7 @@ class EditPage {
                                if ( $revision ) {
                                        // Let sysop know that this will make private content public if saved
 
-                                       if ( !$revision->userCan( Revision::DELETED_TEXT, $wgUser ) ) {
+                                       if ( !$revision->userCan( Revision::DELETED_TEXT ) ) {
                                                $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", 'rev-deleted-text-permission' );
                                        } elseif ( $revision->isDeleted( Revision::DELETED_TEXT ) ) {
                                                $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", 'rev-deleted-text-view' );
@@ -2253,13 +2269,10 @@ class EditPage {
                                        $wgOut->wrapWikiMsg( "<div class='error' id='mw-userinvalidcssjstitle'>\n$1\n</div>", array( 'userinvalidcssjstitle', $this->mTitle->getSkinFromCssJsSubpage() ) );
                                }
                                if ( $this->formtype !== 'preview' ) {
-                                       if ( $this->isCssSubpage ) {
+                                       if ( $this->isCssSubpage )
                                                $wgOut->wrapWikiMsg( "<div id='mw-usercssyoucanpreview'>\n$1\n</div>", array( 'usercssyoucanpreview' ) );
-                                       }
-
-                                       if ( $this->isJsSubpage ) {
+                                       if ( $this->isJsSubpage )
                                                $wgOut->wrapWikiMsg( "<div id='mw-userjsyoucanpreview'>\n$1\n</div>", array( 'userjsyoucanpreview' ) );
-                                       }
                                }
                        }
                }
@@ -2390,16 +2403,14 @@ class EditPage {
         * @return String
         */
        protected function getSummaryPreview( $isSubjectPreview, $summary = "" ) {
-               if ( !$summary || ( !$this->preview && !$this->diff ) ) {
+               if ( !$summary || ( !$this->preview && !$this->diff ) )
                        return "";
-               }
 
                global $wgParser;
 
-               if ( $isSubjectPreview ) {
+               if ( $isSubjectPreview )
                        $summary = wfMessage( 'newsectionsummary', $wgParser->stripSectionName( $summary ) )
                                ->inContentLanguage()->text();
-               }
 
                $message = $isSubjectPreview ? 'subject-preview' : 'summary-preview';
 
@@ -2418,9 +2429,8 @@ class EditPage {
 
 HTML
                );
-               if ( !$this->checkUnicodeCompliantBrowser() ) {
+               if ( !$this->checkUnicodeCompliantBrowser() )
                        $wgOut->addHTML( Html::hidden( 'safemode', '1' ) );
-               }
        }
 
        protected function showFormAfterText() {
@@ -2536,9 +2546,8 @@ HTML
 
                $attribs = array( 'id' => 'wikiPreview', 'class' => implode( ' ', $classes ) );
 
-               if ( $this->formtype != 'preview' ) {
+               if ( $this->formtype != 'preview' )
                        $attribs['style'] = 'display: none;';
-               }
 
                $wgOut->addHTML( Xml::openElement( 'div', $attribs ) );
 
@@ -2552,7 +2561,7 @@ HTML
                        try {
                                $this->showDiff();
                        } catch ( MWContentSerializationException $ex ) {
-                               $msg = wfMessage( 'content-failed-to-parse', $this->content_model, $this->content_format, $ex->getMessage() );
+                               $msg = wfMessage( 'content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage() );
                                $wgOut->addWikiText( '<div class="error">' . $msg->text() . '</div>');
                        }
                }
@@ -2586,7 +2595,7 @@ HTML
         * save and then make a comparison.
         */
        function showDiff() {
-               global $wgUser, $wgContLang, $wgParser, $wgOut;
+               global $wgUser, $wgContLang, $wgOut;
 
                $oldtitlemsg = 'currentrev';
                # if message does not exist, show diff against the preloaded default
@@ -2605,19 +2614,29 @@ HTML
                $textboxContent = $this->toEditContent( $this->textbox1 );
 
                $newContent = $this->mArticle->replaceSectionContent(
-                                                                                       $this->section, $textboxContent,
-                                                                                       $this->summary, $this->edittime );
+                                                       $this->section, $textboxContent,
+                                                       $this->summary, $this->edittime );
 
-               ContentHandler::runLegacyHooks( 'EditPageGetDiffText', array( $this, &$newContent ) );
-               wfRunHooks( 'EditPageGetDiffContent', array( $this, &$newContent ) );
+               if ( $newContent ) {
+                       ContentHandler::runLegacyHooks( 'EditPageGetDiffText', array( $this, &$newContent ) );
+                       wfRunHooks( 'EditPageGetDiffContent', array( $this, &$newContent ) );
 
-               $popts = ParserOptions::newFromUserAndLang( $wgUser, $wgContLang );
-               $newContent = $newContent->preSaveTransform( $this->mTitle, $wgUser, $popts );
+                       $popts = ParserOptions::newFromUserAndLang( $wgUser, $wgContLang );
+                       $newContent = $newContent->preSaveTransform( $this->mTitle, $wgUser, $popts );
+               }
 
                if ( ( $oldContent && !$oldContent->isEmpty() ) || ( $newContent && !$newContent->isEmpty() ) ) {
                        $oldtitle = wfMessage( $oldtitlemsg )->parse();
                        $newtitle = wfMessage( 'yourtext' )->parse();
 
+                       if ( !$oldContent ) {
+                               $oldContent = $newContent->getContentHandler()->makeEmptyContent();
+                       }
+
+                       if ( !$newContent ) {
+                               $newContent = $oldContent->getContentHandler()->makeEmptyContent();
+                       }
+
                        $de = $oldContent->getContentHandler()->createDifferenceEngine( $this->mArticle->getContext() );
                        $de->setContent( $oldContent, $newContent );
 
@@ -2740,10 +2759,10 @@ HTML
                        $content1 = $this->toEditContent( $this->textbox1 );
                        $content2 = $this->toEditContent( $this->textbox2 );
 
-                       $handler = ContentHandler::getForModelID( $this->content_model );
+                       $handler = ContentHandler::getForModelID( $this->contentModel );
                        $de = $handler->createDifferenceEngine( $this->mArticle->getContext() );
                        $de->setContent( $content2, $content1 );
-                       $de->showDiff( 
+                       $de->showDiff(
                                wfMessage( 'yourtext' )->parse(),
                                wfMessage( 'storedversion' )->text()
                        );
@@ -2833,23 +2852,21 @@ HTML
                );
                // Quick paranoid permission checks...
                if ( is_object( $data ) ) {
-                       if ( $data->log_deleted & LogPage::DELETED_USER ) {
+                       if ( $data->log_deleted & LogPage::DELETED_USER )
                                $data->user_name = wfMessage( 'rev-deleted-user' )->escaped();
-                       }
-
-                       if ( $data->log_deleted & LogPage::DELETED_COMMENT ) {
+                       if ( $data->log_deleted & LogPage::DELETED_COMMENT )
                                $data->log_comment = wfMessage( 'rev-deleted-comment' )->escaped();
-                       }
                }
                return $data;
        }
 
        /**
         * Get the rendered text for previewing.
+        * @throws MWException
         * @return string
         */
        function getPreviewText() {
-               global $wgOut, $wgUser, $wgParser, $wgRawHtml, $wgLang;
+               global $wgOut, $wgUser, $wgRawHtml, $wgLang;
 
                wfProfileIn( __METHOD__ );
 
@@ -2889,7 +2906,6 @@ HTML
 
                        $parserOptions = $this->mArticle->makeParserOptions( $this->mArticle->getContext() );
                        $parserOptions->setEditSection( false );
-                       $parserOptions->setTidy( true );
                        $parserOptions->setIsPreview( true );
                        $parserOptions->setIsSectionPreview( !is_null($this->section) && $this->section !== '' );
 
@@ -2929,7 +2945,7 @@ HTML
 
                                # If we're adding a comment, we need to show the
                                # summary as the headline
-                               if ( $this->section == "new" && $this->summary != "" ) {
+                               if ( $this->section === "new" && $this->summary !== "" ) {
                                        $content = $content->addSectionHeader( $this->summary );
                                }
 
@@ -2953,8 +2969,8 @@ HTML
                                        $note .= "\n\n" . implode( "\n\n", $parserOutput->getWarnings() );
                                }
                        }
-               } catch (MWContentSerializationException $ex) {
-                       $m = wfMessage('content-failed-to-parse', $this->content_model, $this->content_format, $ex->getMessage() );
+               } catch ( MWContentSerializationException $ex ) {
+                       $m = wfMessage('content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage() );
                        $note .= "\n\n" . $m->parse();
                        $previewHTML = '';
                }
@@ -3348,7 +3364,7 @@ HTML
        /**
         * Produce the stock "your edit contains spam" page
         *
-        * @param $match string Text which triggered one or more filters
+        * @param $match string|bool Text which triggered one or more filters
         * @deprecated since 1.17 Use method spamPageWithContent() instead
         */
        static function spamPage( $match = false ) {