(bug 13454) Article::updateCategoryCounts can attempt to execute empty inserts.
[lhc/web/wiklou.git] / includes / DifferenceEngine.php
index 8e186c4..83409a6 100644 (file)
@@ -48,7 +48,7 @@ class DifferenceEngine {
                        # Show diff between revision $old and the previous one.
                        # Get previous one from DB.
                        #
-                       $this->mNewid = intval($old); 
+                       $this->mNewid = intval($old);
 
                        $this->mOldid = $this->mTitle->getPreviousRevisionID( $this->mNewid );
 
@@ -64,13 +64,6 @@ class DifferenceEngine {
                                $this->mNewid = 0;
                        }
 
-               } else if( 'cur' === $new ) {
-                       # Show diff between revision $old and the current one.
-                       # Get previous one from DB.
-                       #
-                       $this->mNewid = $this->mTitle->getLatestRevID();
-
-                       $this->mOldid = intval($old);
                } else {
                        $this->mOldid = intval($old);
                        $this->mNewid = intval($new);
@@ -116,9 +109,8 @@ CONTROL;
                $wgOut->setArticleFlag( false );
                if ( ! $this->loadRevisionData() ) {
                        $t = $this->mTitle->getPrefixedText() . " (Diff: {$this->mOldid}, {$this->mNewid})";
-                       $mtext = wfMsg( 'missingarticle', "<nowiki>$t</nowiki>" );
                        $wgOut->setPagetitle( wfMsg( 'errorpagetitle' ) );
-                       $wgOut->addWikitext( $mtext );
+                       $wgOut->addWikiMsg( 'missingarticle', "<nowiki>$t</nowiki>" );
                        wfProfileOut( $fname );
                        return;
                }
@@ -176,12 +168,12 @@ CONTROL;
                                $db = wfGetDB( DB_SLAVE );
                                $change = RecentChange::newFromConds(
                                        array(
-                                               // Add redundant timestamp condition so we can use the
-                                               // existing index
+                                               // Add redundant user,timestamp condition so we can use the existing index
+                                               'rc_user_text'  => $this->mNewRev->getRawUserText(),
                                                'rc_timestamp' => $db->timestamp( $this->mNewRev->getTimestamp() ),
                                                'rc_this_oldid' => $this->mNewid,
                                                'rc_last_oldid' => $this->mOldid,
-                                               'rc_patrolled' => 0,
+                                               'rc_patrolled' => 0
                                        ),
                                        __METHOD__
                                );
@@ -194,11 +186,11 @@ CONTROL;
                        }
                        // Build the link
                        if( $rcid ) {
-                               $patrol = ' [' . $sk->makeKnownLinkObj(
+                               $patrol = ' <span class="patrollink">[' . $sk->makeKnownLinkObj(
                                        $this->mTitle,
                                        wfMsgHtml( 'markaspatrolleddiff' ),
                                        "action=markpatrolled&rcid={$rcid}"
-                               ) . ']';
+                               ) . ']</span>';
                        } else {
                                $patrol = '';
                        }
@@ -291,9 +283,9 @@ CONTROL;
                $wgOut->addHTML( "<hr /><h2>{$this->mPagetitle}</h2>\n" );
                #add deleted rev tag if needed
                if( !$this->mNewRev->userCan(Revision::DELETED_TEXT) ) {
-                       $wgOut->addWikiText( wfMsg( 'rev-deleted-text-permission' ) );
+                       $wgOut->addWikiMsg( 'rev-deleted-text-permission' );
                } else if( $this->mNewRev->isDeleted(Revision::DELETED_TEXT) ) {
-                       $wgOut->addWikiText( wfMsg( 'rev-deleted-text-view' ) );
+                       $wgOut->addWikiMsg( 'rev-deleted-text-view' );
                }
 
                if( !$this->mNewRev->isCurrent() ) {
@@ -305,7 +297,20 @@ CONTROL;
                        $wgOut->setRevisionId( $this->mNewRev->getId() );
                }
 
-               $wgOut->addWikiTextTidy( $this->mNewtext );
+               if ($this->mTitle->isCssJsSubpage() || $this->mTitle->isCssOrJsPage()) {
+                       // Stolen from Article::view --AG 2007-10-11
+
+                       // Give hooks a chance to customise the output
+                       if( wfRunHooks( 'ShowRawCssJs', array( $this->mNewtext, $this->mTitle, $wgOut ) ) ) {
+                               // Wrap the whole lot in a <pre> and don't parse
+                               $m = array();
+                               preg_match( '!\.(css|js)$!u', $this->mTitle->getText(), $m );
+                               $wgOut->addHtml( "<pre class=\"mw-code mw-{$m[1]}\" dir=\"ltr\">\n" );
+                               $wgOut->addHtml( htmlspecialchars( $this->mNewtext ) );
+                               $wgOut->addHtml( "\n</pre>\n" );
+                       }
+               } else
+                       $wgOut->addWikiTextTidy( $this->mNewtext );
 
                if( !$this->mNewRev->isCurrent() ) {
                        $wgOut->parserOptions()->setEditSection( $oldEditSectionSetting );
@@ -329,9 +334,8 @@ CONTROL;
                if ( ! $this->loadNewText() ) {
                        $t = $this->mTitle->getPrefixedText() . " (Diff: {$this->mOldid}, " .
                          "{$this->mNewid})";
-                       $mtext = wfMsg( 'missingarticle', "<nowiki>$t</nowiki>" );
                        $wgOut->setPagetitle( wfMsg( 'errorpagetitle' ) );
-                       $wgOut->addWikitext( $mtext );
+                       $wgOut->addWikiMsg( 'missingarticle', "<nowiki>$t</nowiki>" );
                        wfProfileOut( $fname );
                        return;
                }
@@ -374,7 +378,7 @@ CONTROL;
                global $wgOut;
                $diff = $this->getDiff( $otitle, $ntitle );
                if ( $diff === false ) {
-                       $wgOut->addWikitext( wfMsg( 'missingarticle', "<nowiki>(fixme, bug)</nowiki>" ) );
+                       $wgOut->addWikiMsg( 'missingarticle', "<nowiki>(fixme, bug)</nowiki>" );
                        return false;
                } else {
                        $this->showDiffStyle();
@@ -420,7 +424,12 @@ CONTROL;
                global $wgMemc;
                $fname = 'DifferenceEngine::getDiffBody';
                wfProfileIn( $fname );
-               
+               // Check if the diff should be hidden from this user
+               if ( $this->mOldRev && !$this->mOldRev->userCan(Revision::DELETED_TEXT) ) {
+                       return false;
+               } else if ( $this->mNewRev && !$this->mNewRev->userCan(Revision::DELETED_TEXT) ) {
+                       return false;
+               }
                // Cacheable?
                $key = false;
                if ( $this->mOldid && $this->mNewid ) {
@@ -442,21 +451,12 @@ CONTROL;
                if ( !$this->loadText() ) {
                        wfProfileOut( $fname );
                        return false;
-               } else if ( $this->mOldRev && !$this->mOldRev->userCan(Revision::DELETED_TEXT) ) {
-                       return '';
-               } else if ( $this->mNewRev && !$this->mNewRev->userCan(Revision::DELETED_TEXT) ) {
-                       return '';
                }
 
                $difftext = $this->generateDiffBody( $this->mOldtext, $this->mNewtext );
                
                // Save to cache for 7 days
-               // Only do this for public revs, otherwise an admin can view the diff and a non-admin can nab it!
-               if ( $this->mOldRev && $this->mOldRev->isDeleted(Revision::DELETED_TEXT) ) {
-                       wfIncrStats( 'diff_uncacheable' );
-               } else if ( $this->mNewRev && $this->mNewRev->isDeleted(Revision::DELETED_TEXT) ) {
-                       wfIncrStats( 'diff_uncacheable' );
-               } else if ( $key !== false && $difftext !== false ) {
+               if ( $key !== false && $difftext !== false ) {
                        wfIncrStats( 'diff_cache_miss' );
                        $wgMemc->set( $key, $difftext, 7*86400 );
                } else {
@@ -643,10 +643,10 @@ CONTROL;
                        : Revision::newFromTitle( $this->mTitle );
                if( !$this->mNewRev instanceof Revision )
                        return false;
-
+               
                // Update the new revision ID in case it was 0 (makes life easier doing UI stuff)
                $this->mNewid = $this->mNewRev->getId();
-
+               
                // Set assorted variables
                $timestamp = $wgLang->timeanddate( $this->mNewRev->getTimestamp(), true );
                $this->mNewPage = $this->mNewRev->getTitle();
@@ -661,7 +661,7 @@ CONTROL;
                } else {
                        $newLink = $this->mNewPage->escapeLocalUrl( 'oldid=' . $this->mNewid );
                        $newEdit = $this->mNewPage->escapeLocalUrl( 'action=edit&oldid=' . $this->mNewid );
-                       $this->mPagetitle = htmlspecialchars( wfMsg( 'revisionasof', $timestamp ) );
+                       $this->mPagetitle = wfMsgHTML( 'revisionasof', $timestamp );
 
                        $this->mNewtitle = "<a href='$newLink'>{$this->mPagetitle}</a>"
                                . " (<a href='$newEdit'>" . htmlspecialchars( wfMsg( 'editold' ) ) . "</a>)";
@@ -701,7 +701,7 @@ CONTROL;
                        $this->mOldPagetitle = htmlspecialchars( wfMsg( 'revisionasof', $t ) );
                        
                        $this->mOldtitle = "<a href='$oldLink'>{$this->mOldPagetitle}</a>"
-                               . "(<a href='$oldEdit'>" . htmlspecialchars( wfMsg( 'editold' ) ) . "</a>)";
+                               . " (<a href='$oldEdit'>" . htmlspecialchars( wfMsg( 'editold' ) ) . "</a>)";
                        // Add an "undo" link
                        $newUndo = $this->mNewPage->escapeLocalUrl( 'action=edit&undoafter=' . $this->mOldid . '&undo=' . $this->mNewid);
                        if ( $this->mNewRev->userCan(Revision::DELETED_TEXT) )
@@ -1642,7 +1642,7 @@ class DiffFormatter
        }
 
        function _start_block($header) {
-               echo $header;
+               echo $header . "\n";
        }
 
        function _end_block() {
@@ -1671,6 +1671,84 @@ class DiffFormatter
        }
 }
 
+/**
+ * A formatter that outputs unified diffs
+ * @addtogroup DifferenceEngine
+ */
+
+class UnifiedDiffFormatter extends DiffFormatter
+{
+       var $leading_context_lines = 2;
+       var $trailing_context_lines = 2;
+       
+       function _added($lines) {
+               $this->_lines($lines, '+');
+       }
+       function _deleted($lines) {
+               $this->_lines($lines, '-');
+       }
+       function _changed($orig, $closing) {
+               $this->_deleted($orig);
+               $this->_added($closing);
+       }
+       function _block_header($xbeg, $xlen, $ybeg, $ylen) {
+               return "@@ -$xbeg,$xlen +$ybeg,$ylen @@";
+       }
+}
+
+/**
+ * A pseudo-formatter that just passes along the Diff::$edits array
+ * @addtogroup DifferenceEngine
+ */
+class ArrayDiffFormatter extends DiffFormatter
+{
+       function format($diff)
+       {
+               $oldline = 1;
+               $newline = 1;
+               $retval = array();
+               foreach($diff->edits as $edit)
+                       switch($edit->type)
+                       {
+                               case 'add':
+                                       foreach($edit->closing as $l)
+                                       {
+                                               $retval[] = array(
+                                                       'action' => 'add',
+                                                       'new'=> $l,
+                                                       'newline' => $newline++
+                                               );
+                                       }
+                                       break;
+                               case 'delete':
+                                       foreach($edit->orig as $l)
+                                       {
+                                               $retval[] = array(
+                                                       'action' => 'delete',
+                                                       'old' => $l,
+                                                       'oldline' => $oldline++,
+                                               );
+                                       }
+                                       break;
+                               case 'change':
+                                       foreach($edit->orig as $i => $l)
+                                       {
+                                               $retval[] = array(
+                                                       'action' => 'change',
+                                                       'old' => $l,
+                                                       'new' => @$edit->closing[$i],
+                                                       'oldline' => $oldline++,
+                                                       'newline' => $newline++,
+                                               );
+                                       }
+                                       break;
+                               case 'copy':
+                                       $oldline += count($edit->orig);
+                                       $newline += count($edit->orig);
+                       }
+               return $retval;
+       }                       
+}
 
 /**
  *     Additions by Axel Boldt follow, partly taken from diff.php, phpwiki-1.3.3
@@ -1886,13 +1964,15 @@ class TableDiffFormatter extends DiffFormatter
        function _added( $lines ) {
                foreach ($lines as $line) {
                        echo '<tr>' . $this->emptyLine() .
-                               $this->addedLine( htmlspecialchars ( $line ) ) . "</tr>\n";
+                               $this->addedLine( '<ins class="diffchange">' .
+                                       htmlspecialchars ( $line ) . '</ins>' ) . "</tr>\n";
                }
        }
 
        function _deleted($lines) {
                foreach ($lines as $line) {
-                       echo '<tr>' . $this->deletedLine( htmlspecialchars ( $line ) ) .
+                       echo '<tr>' . $this->deletedLine( '<del class="diffchange">' .
+                               htmlspecialchars ( $line ) . '</del>' ) .
                          $this->emptyLine() . "</tr>\n";
                }
        }