whitespaces
[lhc/web/wiklou.git] / includes / Article.php
index 6576ccb..1b91814 100644 (file)
@@ -57,14 +57,14 @@ class Article {
        function setRedirectedFrom( $from ) {
                $this->mRedirectedFrom = $from;
        }
-       
+
        /**
         * @return mixed false, Title of in-wiki target, or string with URL
         */
        function followRedirect() {
                $text = $this->getContent();
                $rt = Title::newFromRedirect( $text );
-               
+
                # process if title object is valid and not special:userlogout
                if( $rt ) {
                        if( $rt->getInterwiki() != '' ) {
@@ -73,7 +73,7 @@ class Article {
                                        //
                                        // This can be hard to reverse and may produce loops,
                                        // so they may be disabled in the site configuration.
-                                       
+
                                        $source = $this->mTitle->getFullURL( 'redirect=no' );
                                        return $rt->getFullURL( 'rdfrom=' . urlencode( $source ) );
                                }
@@ -84,7 +84,7 @@ class Article {
                                        // the rest of the page we're on.
                                        //
                                        // This can be hard to reverse, so they may be disabled.
-                                       
+
                                        if( $rt->isSpecial( 'Userlogout' ) ) {
                                                // rolleyes
                                        } else {
@@ -94,7 +94,7 @@ class Article {
                                return $rt;
                        }
                }
-               
+
                // No or invalid redirect
                return false;
        }
@@ -299,14 +299,15 @@ class Article {
                        $dbr =& $this->getDB();
                        $data = $this->pageDataFromId( $dbr, $this->getId() );
                }
-                       
+
                $lc =& LinkCache::singleton();
                if ( $data ) {
                        $lc->addGoodLinkObj( $data->page_id, $this->mTitle );
 
                        $this->mTitle->mArticleID = $data->page_id;
+
+                       # Old-fashioned restrictions.
                        $this->mTitle->loadRestrictions( $data->page_restrictions );
-                       $this->mTitle->mRestrictionsLoaded = true;
 
                        $this->mCounter     = $data->page_counter;
                        $this->mTouched     = wfTimestamp( TS_MW, $data->page_touched );
@@ -406,8 +407,7 @@ class Article {
         * @return Database
         */
        function &getDB() {
-               $ret =& wfGetDB( DB_MASTER );
-               return $ret;
+               return wfGetDB( DB_MASTER );
        }
 
        /**
@@ -471,12 +471,12 @@ class Article {
         * @return bool
         */
        function isCountable( $text ) {
-               global $wgUseCommaCount, $wgContentNamespaces;
+               global $wgUseCommaCount;
 
                $token = $wgUseCommaCount ? ',' : '[[';
                return
-                       array_search( $this->mTitle->getNamespace(), $wgContentNamespaces ) !== false
-                       && ! $this->isRedirect( $text )
+                       $this->mTitle->isContentPage()
+                       && !$this->isRedirect( $text )
                        && in_string( $token, $text );
        }
 
@@ -613,7 +613,7 @@ class Article {
 
                $parserCache =& ParserCache::singleton();
                $ns = $this->mTitle->getNamespace(); # shortcut
-               
+
                # Get variables from query string
                $oldid = $this->getOldID();
 
@@ -627,14 +627,21 @@ class Article {
                $diff = $wgRequest->getVal( 'diff' );
                $rcid = $wgRequest->getVal( 'rcid' );
                $rdfrom = $wgRequest->getVal( 'rdfrom' );
+               $diffOnly = $wgRequest->getBool( 'diffonly', $wgUser->getOption( 'diffonly' ) );
 
                $wgOut->setArticleFlag( true );
-               if ( isset( $wgNamespaceRobotPolicies[$ns] ) ) {
+
+               # Discourage indexing of printable versions, but encourage following
+               if( $wgOut->isPrintable() ) {
+                       $policy = 'noindex,follow';
+               } elseif( isset( $wgNamespaceRobotPolicies[$ns] ) ) {
+                       # Honour customised robot policies for this namespace
                        $policy = $wgNamespaceRobotPolicies[$ns];
                } else {
+                       # Default to encourage indexing and following links
                        $policy = 'index,follow';
                }
-               $wgOut->setRobotpolicy( $policy );
+               $wgOut->setRobotPolicy( $policy );
 
                # If we got diff and oldid in the query, we want to see a
                # diff page instead of the article.
@@ -645,8 +652,8 @@ class Article {
                        $de = new DifferenceEngine( $this->mTitle, $oldid, $diff, $rcid );
                        // DifferenceEngine directly fetched the revision:
                        $this->mRevIdFetched = $de->mNewid;
-                       $de->showDiffPage();
-                       
+                       $de->showDiffPage( $diffOnly );
+
                        // Needed to get the page's current revision
                        $this->loadPageData();
                        if( $diff == 0 || $diff == $this->mLatest ) {
@@ -656,7 +663,7 @@ class Article {
                        wfProfileOut( __METHOD__ );
                        return;
                }
-               
+
                if ( empty( $oldid ) && $this->checkTouched() ) {
                        $wgOut->setETag($parserCache->getETag($this, $wgUser));
 
@@ -711,7 +718,7 @@ class Article {
                                $wasRedirected = true;
                        }
                }
-               
+
                $outputDone = false;
                if ( $pcache ) {
                        if ( $wgOut->tryParserCache( $this, $wgUser ) ) {
@@ -786,14 +793,14 @@ class Article {
                                }
                                $link = $sk->makeLinkObj( $rt, $rt->getFullText() );
 
-                               $wgOut->addHTML( '<img src="'.$imageUrl.'" alt="#REDIRECT" />' .
+                               $wgOut->addHTML( '<img src="'.$imageUrl.'" alt="#REDIRECT " />' .
                                  '<span class="redirectText">'.$link.'</span>' );
 
                                $parseout = $wgParser->parse($text, $this->mTitle, ParserOptions::newFromUser($wgUser));
                                $wgOut->addParserOutputNoText( $parseout );
                        } else if ( $pcache ) {
                                # Display content and save to parser cache
-                               $wgOut->addPrimaryWikiText( $text, $this );
+                               $this->outputWikiText( $text );
                        } else {
                                # Display content, don't attempt to save to parser cache
                                # Don't show section-edit links on old revisions... this way lies madness.
@@ -801,11 +808,21 @@ class Article {
                                        $oldEditSectionSetting = $wgOut->parserOptions()->setEditSection( false );
                                }
                                # Display content and don't save to parser cache
-                               $wgOut->addPrimaryWikiText( $text, $this, false );
+                               # With timing hack -- TS 2006-07-26
+                               $time = -wfTime();
+                               $this->outputWikiText( $text, false );
+                               $time += wfTime();
+
+                               # Timing hack
+                               if ( $time > 3 ) {
+                                       wfDebugLog( 'slow-parse', sprintf( "%-5.2f %s", $time,
+                                               $this->mTitle->getPrefixedDBkey()));
+                               }
 
                                if( !$this->isCurrent() ) {
                                        $wgOut->parserOptions()->setEditSection( $oldEditSectionSetting );
                                }
+
                        }
                }
                /* title may have been set from the cache */
@@ -825,8 +842,9 @@ class Article {
                if ( $wgUseRCPatrol && !is_null( $rcid ) && $rcid != 0 && $wgUser->isAllowed( 'patrol' ) ) {
                        $wgOut->addHTML(
                                "<div class='patrollink'>" .
-                                       wfMsg ( 'markaspatrolledlink',
-                                       $sk->makeKnownLinkObj( $this->mTitle, wfMsg('markaspatrolledtext'), "action=markpatrolled&rcid=$rcid" )
+                                       wfMsgHtml( 'markaspatrolledlink',
+                                       $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml('markaspatrolledtext'),
+                                               "action=markpatrolled&rcid=$rcid" )
                                        ) .
                                '</div>'
                         );
@@ -908,7 +926,7 @@ class Article {
        function purge() {
                global $wgUser, $wgRequest, $wgOut;
 
-               if ( $wgUser->isLoggedIn() || $wgRequest->wasPosted() ) {
+               if ( $wgUser->isAllowed( 'purge' ) || $wgRequest->wasPosted() ) {
                        if( wfRunHooks( 'ArticlePurge', array( &$this ) ) ) {
                                $this->doPurge();
                        }
@@ -926,7 +944,7 @@ class Article {
                        $wgOut->addHTML( $msg );
                }
        }
-       
+
        /**
         * Perform the actions of a page purging
         */
@@ -968,7 +986,6 @@ class Article {
                        'page_namespace'    => $this->mTitle->getNamespace(),
                        'page_title'        => $this->mTitle->getDBkey(),
                        'page_counter'      => 0,
-                       'page_restrictions' => $restrictions,
                        'page_is_redirect'  => 0, # Will set this shortly...
                        'page_is_new'       => 1,
                        'page_random'       => wfRandom(),
@@ -994,7 +1011,7 @@ class Article {
         *                          when different from the currently set value.
         *                          Giving 0 indicates the new page flag should
         *                          be set on.
-        * @param bool $lastRevIsRedirect If given, will optimize adding and 
+        * @param bool $lastRevIsRedirect If given, will optimize adding and
         *                                                      removing rows in redirect table.
         * @return bool true on success, false on failure
         * @private
@@ -1004,7 +1021,7 @@ class Article {
 
                $text = $revision->getText();
                $rt = Title::newFromRedirect( $text );
-               
+
                $conditions = array( 'page_id' => $this->getId() );
                if( !is_null( $lastRevision ) ) {
                        # An extra check against threads stepping on each other
@@ -1026,20 +1043,20 @@ class Article {
 
                if ($result) {
                        // FIXME: Should the result from updateRedirectOn() be returned instead?
-                       $this->updateRedirectOn( $dbw, $rt, $lastRevIsRedirect ); 
+                       $this->updateRedirectOn( $dbw, $rt, $lastRevIsRedirect );
                }
-               
+
                wfProfileOut( __METHOD__ );
                return $result;
        }
 
        /**
-        * Add row to the redirect table if this is a redirect, remove otherwise. 
+        * Add row to the redirect table if this is a redirect, remove otherwise.
         *
         * @param Database $dbw
         * @param $redirectTitle a title object pointing to the redirect target,
-        *                                                      or NULL if this is not a redirect  
-        * @param bool $lastRevIsRedirect If given, will optimize adding and 
+        *                                                      or NULL if this is not a redirect
+        * @param bool $lastRevIsRedirect If given, will optimize adding and
         *                                                      removing rows in redirect table.
         * @return bool true on success, false on failure
         * @private
@@ -1065,7 +1082,7 @@ class Article {
 
                                $dbw->replace( 'redirect', array( 'rd_from' ), $set, __METHOD__ );
                        } else {
-                               // This is not a redirect, remove row from redirect table 
+                               // This is not a redirect, remove row from redirect table
                                $where = array( 'rd_from' => $this->getId() );
                                $dbw->delete( 'redirect', $where, __METHOD__);
                        }
@@ -1073,7 +1090,7 @@ class Article {
                        wfProfileOut( __METHOD__ );
                        return ( $dbw->affectedRows() != 0 );
                }
-               
+
                return true;
        }
 
@@ -1117,7 +1134,7 @@ class Article {
         */
        function replaceSection($section, $text, $summary = '', $edittime = NULL) {
                wfProfileIn( __METHOD__ );
-               
+
                if( $section == '' ) {
                        // Whole-page edit; let the text through unmolested.
                } else {
@@ -1164,7 +1181,7 @@ class Article {
                if ( $comment && $summary != "" ) {
                        $text = "== {$summary} ==\n\n".$text;
                }
-               
+
                $this->doEdit( $text, $summary, $flags );
 
                $dbw =& wfGetDB( DB_MASTER );
@@ -1217,7 +1234,7 @@ class Article {
        /**
         * Article::doEdit()
         *
-        * Change an existing article or create a new article. Updates RC and all necessary caches, 
+        * Change an existing article or create a new article. Updates RC and all necessary caches,
         * optionally via the deferred update array.
         *
         * $wgUser must be set before calling this function.
@@ -1239,9 +1256,9 @@ class Article {
         *          Defer some of the updates until the end of index.php
         *      EDIT_AUTOSUMMARY
         *          Fill in blank summaries with generated text where possible
-        * 
-        * If neither EDIT_NEW nor EDIT_UPDATE is specified, the status of the article will be detected. 
-        * If EDIT_UPDATE is specified and the article doesn't exist, the function will return false. If 
+        *
+        * If neither EDIT_NEW nor EDIT_UPDATE is specified, the status of the article will be detected.
+        * If EDIT_UPDATE is specified and the article doesn't exist, the function will return false. If
         * EDIT_NEW is specified and the article does exist, a duplicate key error will cause an exception
         * to be thrown from the Database. These two conditions are also possible with auto-detection due
         * to MediaWiki's performance-optimised locking strategy.
@@ -1265,7 +1282,7 @@ class Article {
 
                if( !wfRunHooks( 'ArticleSave', array( &$this, &$wgUser, &$text,
                        &$summary, $flags & EDIT_MINOR,
-                       null, null, &$flags ) ) ) 
+                       null, null, &$flags ) ) )
                {
                        wfDebug( __METHOD__ . ": ArticleSave hook aborted save!\n" );
                        wfProfileOut( __METHOD__ );
@@ -1288,7 +1305,7 @@ class Article {
 
                $dbw =& wfGetDB( DB_MASTER );
                $now = wfTimestampNow();
-               
+
                if ( $flags & EDIT_UPDATE ) {
                        # Update article, but only if changed.
 
@@ -1314,7 +1331,7 @@ class Article {
                                        wfProfileOut( __METHOD__ );
                                        return false;
                                }
-                               
+
                                $revision = new Revision( array(
                                        'page'       => $this->getId(),
                                        'comment'    => $summary,
@@ -1338,10 +1355,11 @@ class Article {
                                                $rcid = RecentChange::notifyEdit( $now, $this->mTitle, $isminor, $wgUser, $summary,
                                                        $lastRevision, $this->getTimestamp(), $bot, '', $oldsize, $newsize,
                                                        $revisionId );
-                                                       
+
                                                # Mark as patrolled if the user can do so
-                                               if( $wgUser->isAllowed( 'patrol' ) ) {
+                                               if( $GLOBALS['wgUseRCPatrol'] && $wgUser->isAllowed( 'autopatrol' ) ) {
                                                        RecentChange::markPatrolled( $rcid );
+                                                       PatrolLog::record( $rcid, true );
                                                }
                                        }
                                        $wgUser->incEditCount();
@@ -1360,19 +1378,19 @@ class Article {
                        }
 
                        if ( $good ) {
-                               # Invalidate cache of this article and all pages using this article 
+                               # Invalidate cache of this article and all pages using this article
                                # as a template. Partly deferred.
                                Article::onArticleEdit( $this->mTitle );
-                               
+
                                # Update links tables, site stats, etc.
                                $changed = ( strcmp( $oldtext, $text ) != 0 );
                                $this->editUpdates( $text, $summary, $isminor, $now, $revisionId, $changed );
                        }
                } else {
                        # Create new article
-                       
+
                        # Set statistics members
-                       # We work out if it's countable after PST to avoid counter drift 
+                       # We work out if it's countable after PST to avoid counter drift
                        # when articles are created with {{subst:}}
                        $this->mGoodAdjustment = (int)$this->isCountable( $text );
                        $this->mTotalAdjustment = 1;
@@ -1401,8 +1419,9 @@ class Article {
                                $rcid = RecentChange::notifyNew( $now, $this->mTitle, $isminor, $wgUser, $summary, $bot,
                                  '', strlen( $text ), $revisionId );
                                # Mark as patrolled if the user can
-                               if( $wgUser->isAllowed( 'patrol' ) ) {
+                               if( $GLOBALS['wgUseRCPatrol'] && $wgUser->isAllowed( 'autopatrol' ) ) {
                                        RecentChange::markPatrolled( $rcid );
+                                       PatrolLog::record( $rcid, true );
                                }
                        }
                        $wgUser->incEditCount();
@@ -1427,7 +1446,7 @@ class Article {
                        array( &$this, &$wgUser, $text,
                        $summary, $flags & EDIT_MINOR,
                        null, null, &$flags ) );
-               
+
                wfProfileOut( __METHOD__ );
                return $good;
        }
@@ -1455,40 +1474,66 @@ class Article {
                }
                $wgOut->redirect( $this->mTitle->getFullURL( $query ) . $sectionAnchor );
        }
-               
+
        /**
         * Mark this particular edit as patrolled
         */
        function markpatrolled() {
                global $wgOut, $wgRequest, $wgUseRCPatrol, $wgUser;
-               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+               $wgOut->setRobotPolicy( 'noindex,nofollow' );
 
                # Check RC patrol config. option
                if( !$wgUseRCPatrol ) {
                        $wgOut->errorPage( 'rcpatroldisabled', 'rcpatroldisabledtext' );
                        return;
                }
-               
+
                # Check permissions
                if( !$wgUser->isAllowed( 'patrol' ) ) {
                        $wgOut->permissionRequired( 'patrol' );
                        return;
                }
-               
+
+               # If we haven't been given an rc_id value, we can't do anything
                $rcid = $wgRequest->getVal( 'rcid' );
-               if ( !is_null ( $rcid ) ) {
-                       if( wfRunHooks( 'MarkPatrolled', array( &$rcid, &$wgUser, false ) ) ) {
-                               RecentChange::markPatrolled( $rcid );
-                               wfRunHooks( 'MarkPatrolledComplete', array( &$rcid, &$wgUser, false ) );
-                               $wgOut->setPagetitle( wfMsg( 'markedaspatrolled' ) );
-                               $wgOut->addWikiText( wfMsg( 'markedaspatrolledtext' ) );
-                       }
-                       $rcTitle = SpecialPage::getTitleFor( 'Recentchanges' );
-                       $wgOut->returnToMain( false, $rcTitle->getPrefixedText() );
+               if( !$rcid ) {
+                       $wgOut->errorPage( 'markedaspatrollederror', 'markedaspatrollederrortext' );
+                       return;
+               }
+
+               # Handle the 'MarkPatrolled' hook
+               if( !wfRunHooks( 'MarkPatrolled', array( $rcid, &$wgUser, false ) ) ) {
+                       return;
                }
-               else {
-                       $wgOut->showErrorPage( 'markedaspatrollederror', 'markedaspatrollederrortext' );
+
+               $return = SpecialPage::getTitleFor( 'Recentchanges' );
+               # If it's left up to us, check that the user is allowed to patrol this edit
+               # If the user has the "autopatrol" right, then we'll assume there are no
+               # other conditions stopping them doing so
+               if( !$wgUser->isAllowed( 'autopatrol' ) ) {
+                       $rc = RecentChange::newFromId( $rcid );
+                       # Graceful error handling, as we've done before here...
+                       # (If the recent change doesn't exist, then it doesn't matter whether
+                       # the user is allowed to patrol it or not; nothing is going to happen
+                       if( is_object( $rc ) && $wgUser->getName() == $rc->getAttribute( 'rc_user_text' ) ) {
+                               # The user made this edit, and can't patrol it
+                               # Tell them so, and then back off
+                               $wgOut->setPageTitle( wfMsg( 'markedaspatrollederror' ) );
+                               $wgOut->addWikiText( wfMsgNoTrans( 'markedaspatrollederror-noautopatrol' ) );
+                               $wgOut->returnToMain( false, $return );
+                               return;
+                       }
                }
+
+               # Mark the edit as patrolled
+               RecentChange::markPatrolled( $rcid );
+               PatrolLog::record( $rcid );
+               wfRunHooks( 'MarkPatrolledComplete', array( &$rcid, &$wgUser, false ) );
+
+               # Inform the user
+               $wgOut->setPageTitle( wfMsg( 'markedaspatrolled' ) );
+               $wgOut->addWikiText( wfMsgNoTrans( 'markedaspatrolledtext' ) );
+               $wgOut->returnToMain( false, $return );
        }
 
        /**
@@ -1507,7 +1552,7 @@ class Article {
                        $wgOut->readOnlyPage();
                        return;
                }
-               
+
                if( $this->doWatch() ) {
                        $wgOut->setPagetitle( wfMsg( 'addedwatch' ) );
                        $wgOut->setRobotpolicy( 'noindex,nofollow' );
@@ -1519,7 +1564,7 @@ class Article {
 
                $wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
        }
-       
+
        /**
         * Add this page to $wgUser's watchlist
         * @return bool true on successful watch operation
@@ -1529,13 +1574,13 @@ class Article {
                if( $wgUser->isAnon() ) {
                        return false;
                }
-               
+
                if (wfRunHooks('WatchArticle', array(&$wgUser, &$this))) {
                        $wgUser->addWatch( $this->mTitle );
 
                        return wfRunHooks('WatchArticleComplete', array(&$wgUser, &$this));
                }
-               
+
                return false;
        }
 
@@ -1554,7 +1599,7 @@ class Article {
                        $wgOut->readOnlyPage();
                        return;
                }
-               
+
                if( $this->doUnwatch() ) {
                        $wgOut->setPagetitle( wfMsg( 'removedwatch' ) );
                        $wgOut->setRobotpolicy( 'noindex,nofollow' );
@@ -1566,7 +1611,7 @@ class Article {
 
                $wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
        }
-       
+
        /**
         * Stop watching a page
         * @return bool true on successful unwatch
@@ -1582,7 +1627,7 @@ class Article {
 
                        return wfRunHooks('UnwatchArticleComplete', array(&$wgUser, &$this));
                }
-               
+
                return false;
        }
 
@@ -1608,14 +1653,18 @@ class Article {
         * @param string $reason
         * @return bool true on success
         */
-       function updateRestrictions( $limit = array(), $reason = '' ) {
+       function updateRestrictions( $limit = array(), $reason = '', $cascade = 0 ) {
                global $wgUser, $wgRestrictionTypes, $wgContLang;
-               
+
                $id = $this->mTitle->getArticleID();
                if( !$wgUser->isAllowed( 'protect' ) || wfReadOnly() || $id == 0 ) {
                        return false;
                }
 
+               if (!$cascade) {
+                       $cascade = false;
+               }
+
                # FIXME: Same limitations as described in ProtectionForm.php (line 37);
                # we expect a single selection, but the schema allows otherwise.
                $current = array();
@@ -1624,16 +1673,17 @@ class Article {
 
                $current = Article::flattenRestrictions( $current );
                $updated = Article::flattenRestrictions( $limit );
-               
+
                $changed = ( $current != $updated );
+               $changed = $changed || ($this->mTitle->areRestrictionsCascading() != $cascade);
                $protect = ( $updated != '' );
-               
+
                # If nothing's changed, do nothing
                if( $changed ) {
                        if( wfRunHooks( 'ArticleProtect', array( &$this, &$wgUser, $limit, $reason ) ) ) {
 
                                $dbw =& wfGetDB( DB_MASTER );
-                               
+
                                # Prepare a null revision to be added to the history
                                $comment = $wgContLang->ucfirst( wfMsgForContent( $protect ? 'protectedarticle' : 'unprotectedarticle', $this->mTitle->getPrefixedText() ) );
                                if( $reason )
@@ -1642,30 +1692,49 @@ class Article {
                                        $comment .= " [$updated]";
                                $nullRevision = Revision::newNullRevision( $dbw, $id, $comment, true );
                                $nullRevId = $nullRevision->insertOn( $dbw );
-                       
+
+                               # Update restrictions table
+                               foreach( $limit as $action => $restrictions ) {
+                                       if ($restrictions != '' ) {
+                                               $dbw->replace( 'page_restrictions', array( 'pr_pagetype'),
+                                                       array( 'pr_page' => $id, 'pr_type' => $action
+                                                               , 'pr_level' => $restrictions, 'pr_cascade' => $cascade ? 1 : 0 ), __METHOD__  );
+                                       } else {
+                                               $dbw->delete( 'page_restrictions', array( 'pr_page' => $id,
+                                                       'pr_type' => $action ), __METHOD__ );
+                                       }
+                               }
+
                                # Update page record
                                $dbw->update( 'page',
                                        array( /* SET */
                                                'page_touched' => $dbw->timestamp(),
-                                               'page_restrictions' => $updated,
+                                               'page_restrictions' => '',
                                                'page_latest' => $nullRevId
                                        ), array( /* WHERE */
                                                'page_id' => $id
                                        ), 'Article::protect'
                                );
                                wfRunHooks( 'ArticleProtectComplete', array( &$this, &$wgUser, $limit, $reason ) );
-       
+
                                # Update the protection log
                                $log = new LogPage( 'protect' );
+
+                               $cascade_description = '';
+
+                               if ($cascade) {
+                                       $cascade_description = ' ['.wfMsg('protect-summary-cascade').']';
+                               }
+
                                if( $protect ) {
-                                       $log->addEntry( 'protect', $this->mTitle, trim( $reason . " [$updated]" ) );
+                                       $log->addEntry( 'protect', $this->mTitle, trim( $reason . " [$updated]$cascade_description" ) );
                                } else {
                                        $log->addEntry( 'unprotect', $this->mTitle, $reason );
                                }
-                               
+
                        } # End hook
                } # End "changed" check
-               
+
                return true;
        }
 
@@ -1718,7 +1787,7 @@ class Article {
                }
 
                $wgOut->setPagetitle( wfMsg( 'confirmdelete' ) );
-               
+
                # Better double-check that it hasn't been deleted yet!
                $dbw =& wfGetDB( DB_MASTER );
                $conds = $this->mTitle->pageCond();
@@ -1742,7 +1811,7 @@ class Article {
                # and insert a warning if it does
                $maxRevisions = 20;
                $authors = $this->getLastNAuthors( $maxRevisions, $latest );
-               
+
                if( count( $authors ) > 1 && !$confirm ) {
                        $skin=$wgUser->getSkin();
                        $wgOut->addHTML( '<strong>' . wfMsg( 'historywarning' ) . ' ' . $skin->historyLink() . '</strong>' );
@@ -1855,7 +1924,7 @@ class Article {
                wfProfileOut( __METHOD__ );
                return $authors;
        }
-       
+
        /**
         * Output deletion confirmation dialog
         */
@@ -1874,7 +1943,7 @@ class Article {
                $confirm = htmlspecialchars( wfMsg( 'deletepage' ) );
                $delcom = htmlspecialchars( wfMsg( 'deletecomment' ) );
                $token = htmlspecialchars( $wgUser->editToken() );
-               $watch = Xml::checkLabel( wfMsg( 'watchthis' ), 'wpWatch', 'wpWatch', $wgUser->getBoolOption( 'watchdeletion' ) || $this->mTitle->userIsWatching() );
+               $watch = Xml::checkLabel( wfMsg( 'watchthis' ), 'wpWatch', 'wpWatch', $wgUser->getBoolOption( 'watchdeletion' ) || $this->mTitle->userIsWatching(), array( 'tabindex' => '2' ) );
 
                $wgOut->addHTML( "
 <form id='deleteconfirm' method='post' action=\"{$formaction}\">
@@ -1884,7 +1953,7 @@ class Article {
                                <label for='wpReason'>{$delcom}:</label>
                        </td>
                        <td align='left'>
-                               <input type='text' size='60' name='wpReason' id='wpReason' value=\"" . htmlspecialchars( $reason ) . "\" />
+                               <input type='text' size='60' name='wpReason' id='wpReason' value=\"" . htmlspecialchars( $reason ) . "\" tabindex=\"1\" />
                        </td>
                </tr>
                <tr>
@@ -1894,7 +1963,7 @@ class Article {
                <tr>
                        <td>&nbsp;</td>
                        <td>
-                               <input type='submit' name='wpConfirmB' id='wpConfirmB' value=\"{$confirm}\" />
+                               <input type='submit' name='wpConfirmB' id='wpConfirmB' value=\"{$confirm}\" tabindex=\"3\" />
                        </td>
                </tr>
        </table>
@@ -1983,6 +2052,9 @@ class Article {
                        ), __METHOD__
                );
 
+               # Delete restrictions for it
+               $dbw->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ );
+
                # Now that it's safely backed up, delete it
                $dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__);
 
@@ -2162,7 +2234,7 @@ class Article {
         * Do standard deferred updates after page edit.
         * Update links tables, site stats, search index and message cache.
         * Every 1000th edit, prune the recent changes table.
-        * 
+        *
         * @private
         * @param $text New text of the article
         * @param $summary Edit summary
@@ -2242,7 +2314,7 @@ class Article {
 
                wfProfileOut( __METHOD__ );
        }
-       
+
        /**
         * Perform article updates on a special page creation.
         *
@@ -2272,8 +2344,8 @@ class Article {
                global $wgLang, $wgOut, $wgUser;
 
                if ( !wfRunHooks( 'DisplayOldSubtitle', array(&$this, &$oldid) ) ) {
-                               return; 
-               }       
+                               return;
+               }
 
                $revision = Revision::newFromId( $oldid );
 
@@ -2299,10 +2371,10 @@ class Article {
                $nextdiff = $current
                        ? wfMsg( 'diff' )
                        : $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'diff' ), 'diff=next&oldid='.$oldid );
-               
+
                $userlinks = $sk->userLink( $revision->getUser(), $revision->getUserText() )
                                                . $sk->userToolLinks( $revision->getUser(), $revision->getUserText() );
-               
+
                $r = "\n\t\t\t\t<div id=\"mw-revision-info\">" . wfMsg( 'revision-info', $td, $userlinks ) . "</div>\n" .
                     "\n\t\t\t\t<div id=\"mw-revision-nav\">" . wfMsg( 'revision-nav', $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff ) . "</div>\n\t\t\t";
                $wgOut->setSubtitle( $r );
@@ -2476,7 +2548,7 @@ class Article {
                        if ($wgDBtype == 'mysql')
                                $dbw->query("LOCK TABLES $hitcounterTable WRITE");
                        $tabletype = $wgDBtype == 'mysql' ? "ENGINE=HEAP " : '';
-                       $dbw->query("CREATE TEMPORARY TABLE $acchitsTable $tabletype AS".
+                       $dbw->query("CREATE TEMPORARY TABLE $acchitsTable $tabletype AS ".
                                "SELECT hc_id,COUNT(*) AS hc_n FROM $hitcounterTable ".
                                'GROUP BY hc_id');
                        $dbw->query("DELETE FROM $hitcounterTable");
@@ -2528,7 +2600,7 @@ class Article {
 
                $title->touchLinks();
                $title->purgeSquid();
-               
+
                # File cache
                if ( $wgUseFileCache ) {
                        $cm = new HTMLFileCache( $title );
@@ -2681,7 +2753,7 @@ class Article {
                $dbr->freeResult( $res );
                return $result;
        }
-       
+
        /**
         * Return an auto-generated summary if the text provided is a redirect.
         *
@@ -2746,8 +2818,10 @@ class Article {
                if ($flags & EDIT_NEW && strlen($newtext)) {
                        #If they're making a new article, give its text, truncated, in the summary.
                        global $wgContLang;
-                       $truncatedtext = $wgContLang->truncate( $newtext, max( 0, 200 - 
-                               strlen( wfMsgForContent( 'autosumm-new') ) ), '...' );
+                       $truncatedtext = $wgContLang->truncate(
+                               str_replace("\n", ' ', $newtext),
+                               max( 0, 200 - strlen( wfMsgForContent( 'autosumm-new') ) ),
+                               '...' );
                        $summary = wfMsgForContent( 'autosumm-new', $truncatedtext );
                }
 
@@ -2756,6 +2830,84 @@ class Article {
 
                return $summary;
        }
+
+       /**
+        * Add the primary page-view wikitext to the output buffer
+        * Saves the text into the parser cache if possible.
+        * Updates templatelinks if it is out of date.
+        *
+        * @param string  $text
+        * @param bool    $cache
+        */
+       public function outputWikiText( $text, $cache = true ) {
+               global $wgParser, $wgUser, $wgOut;
+
+               $popts = $wgOut->parserOptions();
+               $popts->setTidy(true);
+               $parserOutput = $wgParser->parse( $text, $this->mTitle,
+                       $popts, true, true, $this->getRevIdFetched() );
+               $popts->setTidy(false);
+               if ( $cache && $this && $parserOutput->getCacheTime() != -1 ) {
+                       $parserCache =& ParserCache::singleton();
+                       $parserCache->save( $parserOutput, $this, $wgUser );
+               }
+
+               if ( !wfReadOnly() && $this->mTitle->areRestrictionsCascading() ) {
+                       // templatelinks table may have become out of sync,
+                       // especially if using variable-based transclusions.
+                       // For paranoia, check if things have changed and if
+                       // so apply updates to the database. This will ensure
+                       // that cascaded protections apply as soon as the changes
+                       // are visible.
+
+                       # Get templates from templatelinks
+                       $id = $this->mTitle->getArticleID();
+
+                       $tlTemplates = array();
+
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       $res = $dbr->select( array( 'templatelinks' ),
+                               array( 'tl_namespace', 'tl_title' ),
+                               array( 'tl_from' => $id ),
+                               'Article:getUsedTemplates' );
+
+                       global $wgContLang;
+
+                       if ( false !== $res ) {
+                               if ( $dbr->numRows( $res ) ) {
+                                       while ( $row = $dbr->fetchObject( $res ) ) {
+                                               $tlTemplates[] = $wgContLang->getNsText( $row->tl_namespace ) . ':' . $row->tl_title ;
+                                       }
+                               }
+                       }
+
+                       # Get templates from parser output.
+                       $poTemplates_allns = $parserOutput->getTemplates();
+
+                       $poTemplates = array ();
+                       foreach ( $poTemplates_allns as $ns_templates ) {
+                               $poTemplates = array_merge( $poTemplates, $ns_templates );
+                       }
+
+                       # Get the diff
+                       $templates_diff = array_diff( $poTemplates, $tlTemplates );
+
+                       if ( count( $templates_diff ) > 0 ) {
+                               # Whee, link updates time.
+                               $u = new LinksUpdate( $this->mTitle, $parserOutput );
+
+                               $dbw =& wfGetDb( DB_MASTER );
+                               $dbw->begin();
+
+                               $u->doUpdate();
+
+                               $dbw->commit();
+                       }
+               }
+
+               $wgOut->addParserOutput( $parserOutput );
+       }
+
 }
 
 ?>