Merge "Http::getProxy() method to get proxy configuration"
[lhc/web/wiklou.git] / includes / diff / DifferenceEngine.php
index d588d51..4fdacc5 100644 (file)
@@ -180,16 +180,16 @@ class DifferenceEngine extends ContextSource {
                if ( $this->getUser()->isAllowed( 'deletedhistory' ) ) {
                        $dbr = wfGetDB( DB_SLAVE );
                        $row = $dbr->selectRow( 'archive', '*',
-                               array( 'ar_rev_id' => $id ),
+                               [ 'ar_rev_id' => $id ],
                                __METHOD__ );
                        if ( $row ) {
                                $rev = Revision::newFromArchiveRow( $row );
                                $title = Title::makeTitleSafe( $row->ar_namespace, $row->ar_title );
 
-                               return SpecialPage::getTitleFor( 'Undelete' )->getFullURL( array(
+                               return SpecialPage::getTitleFor( 'Undelete' )->getFullURL( [
                                        'target' => $title->getPrefixedText(),
                                        'timestamp' => $rev->getTimestamp()
-                               ) );
+                               ] );
                        }
                }
 
@@ -215,7 +215,7 @@ class DifferenceEngine extends ContextSource {
        private function showMissingRevision() {
                $out = $this->getOutput();
 
-               $missing = array();
+               $missing = [];
                if ( $this->mOldRev === null ||
                        ( $this->mOldRev && $this->mOldContent === null )
                ) {
@@ -232,7 +232,7 @@ class DifferenceEngine extends ContextSource {
                        ->params( $this->getLanguage()->listToText( $missing ) )
                        ->numParams( count( $missing ) )
                        ->parseAsBlock();
-               $out->addHtml( $msg );
+               $out->addHTML( $msg );
        }
 
        public function showDiffPage( $diffOnly = false ) {
@@ -260,7 +260,7 @@ class DifferenceEngine extends ContextSource {
 
                $rollback = '';
 
-               $query = array();
+               $query = [];
                # Carry over 'diffonly' param via navigation links
                if ( $diffOnly != $user->getBoolOption( 'diffonly' ) ) {
                        $query['diffonly'] = $diffOnly;
@@ -274,7 +274,7 @@ class DifferenceEngine extends ContextSource {
                $deleted = $suppressed = false;
                $allowed = $this->mNewRev->userCan( Revision::DELETED_TEXT, $user );
 
-               $revisionTools = array();
+               $revisionTools = [];
 
                # mOldRev is false if the difference engine is called with a "vague" query for
                # a diff between a version V and its previous version V' AND the version V
@@ -284,7 +284,7 @@ class DifferenceEngine extends ContextSource {
                        $samePage = true;
                        $oldHeader = '';
                } else {
-                       Hooks::run( 'DiffViewHeader', array( $this, $this->mOldRev, $this->mNewRev ) );
+                       Hooks::run( 'DiffViewHeader', [ $this, $this->mOldRev, $this->mNewRev ] );
 
                        if ( $this->mNewPage->equals( $this->mOldPage ) ) {
                                $out->setPageTitle( $this->msg( 'difference-title', $this->mNewPage->getPrefixedText() ) );
@@ -308,14 +308,14 @@ class DifferenceEngine extends ContextSource {
                                if ( !$this->mOldRev->isDeleted( Revision::DELETED_TEXT ) &&
                                        !$this->mNewRev->isDeleted( Revision::DELETED_TEXT )
                                ) {
-                                       $undoLink = Html::element( 'a', array(
-                                                       'href' => $this->mNewPage->getLocalURL( array(
+                                       $undoLink = Html::element( 'a', [
+                                                       'href' => $this->mNewPage->getLocalURL( [
                                                                'action' => 'edit',
                                                                'undoafter' => $this->mOldid,
                                                                'undo' => $this->mNewid
-                                                       ) ),
+                                                       ] ),
                                                        'title' => Linker::titleAttrib( 'undo' ),
-                                               ),
+                                               ],
                                                $this->msg( 'editundo' )->text()
                                        );
                                        $revisionTools['mw-diff-undo'] = $undoLink;
@@ -327,8 +327,8 @@ class DifferenceEngine extends ContextSource {
                                $prevlink = Linker::linkKnown(
                                        $this->mOldPage,
                                        $this->msg( 'previousdiff' )->escaped(),
-                                       array( 'id' => 'differences-prevlink' ),
-                                       array( 'diff' => 'prev', 'oldid' => $this->mOldid ) + $query
+                                       [ 'id' => 'differences-prevlink' ],
+                                       [ 'diff' => 'prev', 'oldid' => $this->mOldid ] + $query
                                );
                        } else {
                                $prevlink = ' ';
@@ -342,7 +342,7 @@ class DifferenceEngine extends ContextSource {
 
                        $ldel = $this->revisionDeleteLink( $this->mOldRev );
                        $oldRevisionHeader = $this->getRevisionHeader( $this->mOldRev, 'complete' );
-                       $oldChangeTags = ChangeTags::formatSummaryRow( $this->mOldTags, 'diff' );
+                       $oldChangeTags = ChangeTags::formatSummaryRow( $this->mOldTags, 'diff', $this->getContext() );
 
                        $oldHeader = '<div id="mw-diff-otitle1"><strong>' . $oldRevisionHeader . '</strong></div>' .
                                '<div id="mw-diff-otitle2">' .
@@ -371,8 +371,8 @@ class DifferenceEngine extends ContextSource {
                        $nextlink = Linker::linkKnown(
                                $this->mNewPage,
                                $this->msg( 'nextdiff' )->escaped(),
-                               array( 'id' => 'differences-nextlink' ),
-                               array( 'diff' => 'next', 'oldid' => $this->mNewid ) + $query
+                               [ 'id' => 'differences-nextlink' ],
+                               [ 'diff' => 'next', 'oldid' => $this->mNewid ] + $query
                        );
                } else {
                        $nextlink = '&#160;';
@@ -389,21 +389,21 @@ class DifferenceEngine extends ContextSource {
 
                # Allow extensions to define their own revision tools
                Hooks::run( 'DiffRevisionTools',
-                       array( $this->mNewRev, &$revisionTools, $this->mOldRev, $user ) );
-               $formattedRevisionTools = array();
+                       [ $this->mNewRev, &$revisionTools, $this->mOldRev, $user ] );
+               $formattedRevisionTools = [];
                // Put each one in parentheses (poor man's button)
                foreach ( $revisionTools as $key => $tool ) {
                        $toolClass = is_string( $key ) ? $key : 'mw-diff-tool';
                        $element = Html::rawElement(
                                'span',
-                               array( 'class' => $toolClass ),
+                               [ 'class' => $toolClass ],
                                $this->msg( 'parentheses' )->rawParams( $tool )->escaped()
                        );
                        $formattedRevisionTools[] = $element;
                }
                $newRevisionHeader = $this->getRevisionHeader( $this->mNewRev, 'complete' ) .
                        ' ' . implode( ' ', $formattedRevisionTools );
-               $newChangeTags = ChangeTags::formatSummaryRow( $this->mNewTags, 'diff' );
+               $newChangeTags = ChangeTags::formatSummaryRow( $this->mNewTags, 'diff', $this->getContext() );
 
                $newHeader = '<div id="mw-diff-ntitle1"><strong>' . $newRevisionHeader . '</strong></div>' .
                        '<div id="mw-diff-ntitle2">' . Linker::revUserTools( $this->mNewRev, !$this->unhide ) .
@@ -430,7 +430,7 @@ class DifferenceEngine extends ContextSource {
                                $msg = $suppressed ? 'rev-suppressed-no-diff' : 'rev-deleted-no-diff';
                                # Give explanation for why revision is not visible
                                $out->wrapWikiMsg( "<div id='mw-$msg' class='mw-warning plainlinks'>\n$1\n</div>\n",
-                                       array( $msg ) );
+                                       [ $msg ] );
                        } else {
                                # Give explanation and add a link to view the diff...
                                $query = $this->getRequest()->appendQueryValue( 'unhide', '1' );
@@ -438,7 +438,7 @@ class DifferenceEngine extends ContextSource {
                                $msg = $suppressed ? 'rev-suppressed-unhide-diff' : 'rev-deleted-unhide-diff';
                                $out->wrapWikiMsg(
                                        "<div id='mw-$msg' class='mw-warning plainlinks'>\n$1\n</div>\n",
-                                       array( $msg, $link )
+                                       [ $msg, $link ]
                                );
                        }
                # Otherwise, output a regular diff...
@@ -477,12 +477,12 @@ class DifferenceEngine extends ContextSource {
                                $this->mMarkPatrolledLink = ' <span class="patrollink">[' . Linker::linkKnown(
                                        $this->mNewPage,
                                        $this->msg( 'markaspatrolleddiff' )->escaped(),
-                                       array(),
-                                       array(
+                                       [],
+                                       [
                                                'action' => 'markpatrolled',
                                                'rcid' => $linkInfo['rcid'],
                                                'token' => $linkInfo['token'],
-                                       )
+                                       ]
                                ) . ']</span>';
                        }
                }
@@ -512,11 +512,11 @@ class DifferenceEngine extends ContextSource {
                        // Look for an unpatrolled change corresponding to this diff
                        $db = wfGetDB( DB_SLAVE );
                        $change = RecentChange::newFromConds(
-                               array(
+                               [
                                        'rc_timestamp' => $db->timestamp( $this->mNewRev->getTimestamp() ),
                                        'rc_this_oldid' => $this->mNewid,
                                        'rc_patrolled' => 0
-                               ),
+                               ],
                                __METHOD__
                        );
 
@@ -537,10 +537,10 @@ class DifferenceEngine extends ContextSource {
                                }
 
                                $token = $user->getEditToken( $rcid );
-                               return array(
+                               return [
                                        'rcid' => $rcid,
                                        'token' => $token,
-                               );
+                               ];
                        }
                }
 
@@ -573,7 +573,7 @@ class DifferenceEngine extends ContextSource {
                <h2 class='diff-currentversion-title'>{$revHeader}</h2>\n" );
                # Page content may be handled by a hooked call instead...
                # @codingStandardsIgnoreStart Ignoring long lines.
-               if ( Hooks::run( 'ArticleContentOnDiff', array( $this, $out ) ) ) {
+               if ( Hooks::run( 'ArticleContentOnDiff', [ $this, $out ] ) ) {
                        $this->loadNewText();
                        $out->setRevisionId( $this->mNewid );
                        $out->setRevisionTimestamp( $this->mNewRev->getTimestamp() );
@@ -584,7 +584,7 @@ class DifferenceEngine extends ContextSource {
                                // This needs to be synchronised with Article::showCssOrJsPage(), which sucks
                                // Give hooks a chance to customise the output
                                // @todo standardize this crap into one function
-                               if ( ContentHandler::runLegacyHooks( 'ShowRawCssJs', array( $this->mNewContent, $this->mNewPage, $out ) ) ) {
+                               if ( ContentHandler::runLegacyHooks( 'ShowRawCssJs', [ $this->mNewContent, $this->mNewPage, $out ] ) ) {
                                        // NOTE: deprecated hook, B/C only
                                        // use the content object's own rendering
                                        $cnt = $this->mNewRev->getContent();
@@ -593,9 +593,9 @@ class DifferenceEngine extends ContextSource {
                                                $out->addParserOutputContent( $po );
                                        }
                                }
-                       } elseif ( !Hooks::run( 'ArticleContentViewCustom', array( $this->mNewContent, $this->mNewPage, $out ) ) ) {
+                       } elseif ( !Hooks::run( 'ArticleContentViewCustom', [ $this->mNewContent, $this->mNewPage, $out ] ) ) {
                                // Handled by extension
-                       } elseif ( !ContentHandler::runLegacyHooks( 'ArticleViewCustom', array( $this->mNewContent, $this->mNewPage, $out ) ) ) {
+                       } elseif ( !ContentHandler::runLegacyHooks( 'ArticleViewCustom', [ $this->mNewContent, $this->mNewPage, $out ] ) ) {
                                // NOTE: deprecated hook, B/C only
                                // Handled by extension
                        } else {
@@ -715,7 +715,7 @@ class DifferenceEngine extends ContextSource {
                }
                // Short-circuit
                if ( $this->mOldRev === false || ( $this->mOldRev && $this->mNewRev
-                       && $this->mOldRev->getID() == $this->mNewRev->getID() )
+                       && $this->mOldRev->getId() == $this->mNewRev->getId() )
                ) {
                        return '';
                }
@@ -747,7 +747,7 @@ class DifferenceEngine extends ContextSource {
                $difftext = $this->generateContentDiffBody( $this->mOldContent, $this->mNewContent );
 
                // Save to cache for 7 days
-               if ( !Hooks::run( 'AbortDiffCache', array( &$this ) ) ) {
+               if ( !Hooks::run( 'AbortDiffCache', [ &$this ] ) ) {
                        wfIncrStats( 'diff_cache.uncacheable' );
                } elseif ( $key !== false && $difftext !== false ) {
                        wfIncrStats( 'diff_cache.miss' );
@@ -842,30 +842,49 @@ class DifferenceEngine extends ContextSource {
         * @return bool|string
         */
        public function generateTextDiffBody( $otext, $ntext ) {
+               $time = microtime( true );
+
+               $result = $this->textDiff( $otext, $ntext );
+
+               $time = intval( ( microtime( true ) - $time ) * 1000 );
+               $this->getStats()->timing( 'diff_time', $time );
+               // Log requests slower than 99th percentile
+               if ( $time > 100 && $this->mOldPage && $this->mNewPage ) {
+                       wfDebugLog( 'diff',
+                               "$time ms diff: {$this->mOldid} -> {$this->mNewid} {$this->mNewPage}" );
+               }
+
+               return $result;
+       }
+
+       /**
+        * Generates diff, to be wrapped internally in a logging/instrumentation
+        *
+        * @param string $otext Old text, must be already segmented
+        * @param string $ntext New text, must be already segmented
+        * @return bool|string
+        */
+       protected function textDiff( $otext, $ntext ) {
                global $wgExternalDiffEngine, $wgContLang;
 
                $otext = str_replace( "\r\n", "\n", $otext );
                $ntext = str_replace( "\r\n", "\n", $ntext );
 
-               if ( $wgExternalDiffEngine == 'wikidiff' && function_exists( 'wikidiff_do_diff' ) ) {
-                       # For historical reasons, external diff engine expects
-                       # input text to be HTML-escaped already
-                       $otext = htmlspecialchars( $wgContLang->segmentForDiff( $otext ) );
-                       $ntext = htmlspecialchars( $wgContLang->segmentForDiff( $ntext ) );
-
-                       return $wgContLang->unsegmentForDiff( wikidiff_do_diff( $otext, $ntext, 2 ) ) .
-                       $this->debug( 'wikidiff1' );
+               if ( $wgExternalDiffEngine == 'wikidiff' ) {
+                       wfDeprecated( 'wikidiff support', '1.27' );
+                       $wgExternalDiffEngine = false;
                }
 
-               if ( $wgExternalDiffEngine == 'wikidiff2' && function_exists( 'wikidiff2_do_diff' ) ) {
-                       # Better external diff engine, the 2 may some day be dropped
-                       # This one does the escaping and segmenting itself
-                       $text = wikidiff2_do_diff( $otext, $ntext, 2 );
-                       $text .= $this->debug( 'wikidiff2' );
+               if ( $wgExternalDiffEngine == 'wikidiff2' ) {
+                       if ( function_exists( 'wikidiff2_do_diff' ) ) {
+                               # Better external diff engine, the 2 may some day be dropped
+                               # This one does the escaping and segmenting itself
+                               $text = wikidiff2_do_diff( $otext, $ntext, 2 );
+                               $text .= $this->debug( 'wikidiff2' );
 
-                       return $text;
-               }
-               if ( $wgExternalDiffEngine != 'wikidiff3' && $wgExternalDiffEngine !== false ) {
+                               return $text;
+                       }
+               } elseif ( $wgExternalDiffEngine != 'wikidiff3' && $wgExternalDiffEngine !== false ) {
                        # Diff via the shell
                        $tmpDir = wfTempDir();
                        $tempName1 = tempnam( $tmpDir, 'diff_' );
@@ -915,7 +934,7 @@ class DifferenceEngine extends ContextSource {
                if ( !$this->enableDebugComment ) {
                        return '';
                }
-               $data = array( $generator );
+               $data = [ $generator ];
                if ( $wgShowHostnames ) {
                        $data[] = wfHostname();
                }
@@ -936,7 +955,7 @@ class DifferenceEngine extends ContextSource {
        public function localiseLineNumbers( $text ) {
                return preg_replace_callback(
                        '/<!--LINE (\d+)-->/',
-                       array( &$this, 'localiseLineNumbersCb' ),
+                       [ &$this, 'localiseLineNumbersCb' ],
                        $text
                );
        }
@@ -1040,33 +1059,33 @@ class DifferenceEngine extends ContextSource {
 
                $title = $rev->getTitle();
 
-               $header = Linker::linkKnown( $title, $header, array(),
-                       array( 'oldid' => $rev->getID() ) );
+               $header = Linker::linkKnown( $title, $header, [],
+                       [ 'oldid' => $rev->getId() ] );
 
                if ( $rev->userCan( Revision::DELETED_TEXT, $user ) ) {
-                       $editQuery = array( 'action' => 'edit' );
+                       $editQuery = [ 'action' => 'edit' ];
                        if ( !$rev->isCurrent() ) {
-                               $editQuery['oldid'] = $rev->getID();
+                               $editQuery['oldid'] = $rev->getId();
                        }
 
                        $key = $title->quickUserCan( 'edit', $user ) ? 'editold' : 'viewsourceold';
                        $msg = $this->msg( $key )->escaped();
                        $editLink = $this->msg( 'parentheses' )->rawParams(
-                               Linker::linkKnown( $title, $msg, array(), $editQuery ) )->escaped();
+                               Linker::linkKnown( $title, $msg, [], $editQuery ) )->escaped();
                        $header .= ' ' . Html::rawElement(
                                'span',
-                               array( 'class' => 'mw-diff-edit' ),
+                               [ 'class' => 'mw-diff-edit' ],
                                $editLink
                        );
                        if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
                                $header = Html::rawElement(
                                        'span',
-                                       array( 'class' => 'history-deleted' ),
+                                       [ 'class' => 'history-deleted' ],
                                        $header
                                );
                        }
                } else {
-                       $header = Html::rawElement( 'span', array( 'class' => 'history-deleted' ), $header );
+                       $header = Html::rawElement( 'span', [ 'class' => 'history-deleted' ], $header );
                }
 
                return $header;
@@ -1087,10 +1106,10 @@ class DifferenceEngine extends ContextSource {
        public function addHeader( $diff, $otitle, $ntitle, $multi = '', $notice = '' ) {
                // shared.css sets diff in interface language/dir, but the actual content
                // is often in a different language, mostly the page content language/dir
-               $header = Html::openElement( 'table', array(
-                       'class' => array( 'diff', 'diff-contentalign-' . $this->getDiffLang()->alignStart() ),
+               $header = Html::openElement( 'table', [
+                       'class' => [ 'diff', 'diff-contentalign-' . $this->getDiffLang()->alignStart() ],
                        'data-mw' => 'interface',
-               ) );
+               ] );
                $userLang = htmlspecialchars( $this->getLanguage()->getHtmlCode() );
 
                if ( !$diff && !$otitle ) {
@@ -1195,7 +1214,7 @@ class DifferenceEngine extends ContextSource {
                        $newid = intval( $new );
                }
 
-               return array( $oldid, $newid );
+               return [ $oldid, $newid ];
        }
 
        /**
@@ -1220,7 +1239,7 @@ class DifferenceEngine extends ContextSource {
 
                Hooks::run(
                        'NewDifferenceEngine',
-                       array( $this->getTitle(), &$this->mOldid, &$this->mNewid, $old, $new )
+                       [ $this->getTitle(), &$this->mOldid, &$this->mNewid, $old, $new ]
                );
        }
 
@@ -1295,7 +1314,7 @@ class DifferenceEngine extends ContextSource {
                        $this->mOldTags = $dbr->selectField(
                                'tag_summary',
                                'ts_tags',
-                               array( 'ts_rev_id' => $this->mOldid ),
+                               [ 'ts_rev_id' => $this->mOldid ],
                                __METHOD__
                        );
                } else {
@@ -1304,7 +1323,7 @@ class DifferenceEngine extends ContextSource {
                $this->mNewTags = $dbr->selectField(
                        'tag_summary',
                        'ts_tags',
-                       array( 'ts_rev_id' => $this->mNewid ),
+                       [ 'ts_rev_id' => $this->mNewid ],
                        __METHOD__
                );