Merge "Links created by Linker::makeExternalLink didn't include rel=nofollow"
[lhc/web/wiklou.git] / includes / Linker.php
index 76f6b81..bc0bb77 100644 (file)
@@ -947,10 +947,10 @@ class Linker {
                        return '<a href="' . htmlspecialchars( $href ) . '" class="new" title="' .
                                htmlspecialchars( $title->getPrefixedText(), ENT_QUOTES ) . '">' .
                                $encLabel . '</a>';
-               } else {
-                       wfProfileOut( __METHOD__ );
-                       return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) );
                }
+
+               wfProfileOut( __METHOD__ );
+               return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) );
        }
 
        /**
@@ -1248,7 +1248,7 @@ class Linker {
        /**
         * This function is called by all recent changes variants, by the page history,
         * and by the user contributions list. It is responsible for formatting edit
-        * comments. It escapes any HTML in the comment, but adds some CSS to format
+        * summaries. It escapes any HTML in the summary, but adds some CSS to format
         * auto-generated comments (from section editing) and formats [[wikilinks]].
         *
         * @author Erik Moeller <moeller@scireview.de>
@@ -1285,6 +1285,7 @@ class Linker {
        static $autocommentLocal;
 
        /**
+        * Converts autogenerated comments in edit summaries into section links.
         * The pattern for autogen comments is / * foo * /, which makes for
         * some nasty regex.
         * We look for all comments, match any text before and after the comment,
@@ -1310,6 +1311,7 @@ class Linker {
        }
 
        /**
+        * Helper function for Linker::formatAutocomments
         * @param $match
         * @return string
         */
@@ -1761,19 +1763,101 @@ class Linker {
         * changes, so this allows sysops to combat a busy vandal without bothering
         * other users.
         *
+        * If the option verify is set this function will return the link only in case the
+        * revision can be reverted. Please note that due to performance limitations
+        * it might be assumed that a user isn't the only contributor of a page while
+        * (s)he is, which will lead to useless rollback links. Furthermore this wont
+        * work if $wgShowRollbackEditCount is disabled, so this can only function
+        * as an additional check.
+        *
+        * If the option noBrackets is set the rollback link wont be enclosed in []
+        *
         * @param $rev Revision object
         * @param $context IContextSource context to use or null for the main context.
+        * @param $options array
         * @return string
         */
-       public static function generateRollback( $rev, IContextSource $context = null ) {
+       public static function generateRollback( $rev, IContextSource $context = null, $options = array( 'verify' ) ) {
                if ( $context === null ) {
                        $context = RequestContext::getMain();
                }
+               $editCount = false;
+               if ( in_array( 'verify', $options ) ) {
+                       $editCount = self::getRollbackEditCount( $rev, true );
+                       if ( $editCount === false ) {
+                               return '';
+                       }
+               }
+
+               $inner = self::buildRollbackLink( $rev, $context, $editCount );
+
+               if ( !in_array( 'noBrackets', $options ) ) {
+                       $inner = $context->msg( 'brackets' )->rawParams( $inner )->plain();
+               }
 
-               return '<span class="mw-rollback-link">'
-                       . $context->msg( 'brackets' )->rawParams(
-                               self::buildRollbackLink( $rev, $context ) )->plain()
-                       . '</span>';
+               return '<span class="mw-rollback-link">' . $inner . '</span>';
+       }
+
+       /**
+        * This function will return the number of revisions which a rollback
+        * would revert and, if $verify is set it will verify that a revision
+        * can be reverted (that the user isn't the only contributor and the
+        * revision we might rollback to isn't deleted). These checks can only
+        * function as an additional check as this function only checks against
+        * the last $wgShowRollbackEditCount edits.
+        *
+        * Returns null if $wgShowRollbackEditCount is disabled or false if $verify
+        * is set and the user is the only contributor of the page.
+        *
+        * @param $rev Revision object
+        * @param $verify Bool Try to verfiy that this revision can really be rolled back
+        * @return integer|bool|null
+        */
+       public static function getRollbackEditCount( $rev, $verify ) {
+               global $wgShowRollbackEditCount;
+               if ( !is_int( $wgShowRollbackEditCount ) || !$wgShowRollbackEditCount > 0 ) {
+                       // Nothing has happened, indicate this by returning 'null'
+                       return null;
+               }
+
+               $dbr = wfGetDB( DB_SLAVE );
+
+               // Up to the value of $wgShowRollbackEditCount revisions are counted
+               $res = $dbr->select(
+                       'revision',
+                       array( 'rev_user_text', 'rev_deleted' ),
+                       // $rev->getPage() returns null sometimes
+                       array( 'rev_page' => $rev->getTitle()->getArticleID() ),
+                       __METHOD__,
+                       array(
+                               'USE INDEX' => array( 'revision' => 'page_timestamp' ),
+                               'ORDER BY' => 'rev_timestamp DESC',
+                               'LIMIT' => $wgShowRollbackEditCount + 1
+                       )
+               );
+
+               $editCount = 0;
+               $moreRevs = false;
+               foreach ( $res as $row ) {
+                       if ( $rev->getRawUserText() != $row->rev_user_text ) {
+                               if ( $verify && ( $row->rev_deleted & Revision::DELETED_TEXT || $row->rev_deleted & Revision::DELETED_USER ) ) {
+                                       // If the user or the text of the revision we might rollback to is deleted in some way we can't rollback
+                                       // Similar to the sanity checks in WikiPage::commitRollback
+                                       return false;
+                               }
+                               $moreRevs = true;
+                               break;
+                       }
+                       $editCount++;
+               }
+
+               if ( $verify && $editCount <= $wgShowRollbackEditCount && !$moreRevs ) {
+                       // We didn't find at least $wgShowRollbackEditCount revisions made by the current user
+                       // and there weren't any other revisions. That means that the current user is the only
+                       // editor, so we can't rollback
+                       return false;
+               }
+               return $editCount;
        }
 
        /**
@@ -1781,9 +1865,10 @@ class Linker {
         *
         * @param $rev Revision object
         * @param $context IContextSource context to use or null for the main context.
+        * @param $editCount integer Number of edits that would be reverted
         * @return String: HTML fragment
         */
-       public static function buildRollbackLink( $rev, IContextSource $context = null ) {
+       public static function buildRollbackLink( $rev, IContextSource $context = null, $editCount = false ) {
                global $wgShowRollbackEditCount, $wgMiserMode;
 
                // To config which pages are effected by miser mode
@@ -1815,25 +1900,8 @@ class Linker {
                }
 
                if( !$disableRollbackEditCount && is_int( $wgShowRollbackEditCount ) && $wgShowRollbackEditCount > 0 ) {
-                       $dbr = wfGetDB( DB_SLAVE );
-
-                       // Up to the value of $wgShowRollbackEditCount revisions are counted
-                       $res = $dbr->select( 'revision',
-                               array( 'rev_id', 'rev_user_text' ),
-                               // $rev->getPage() returns null sometimes
-                               array( 'rev_page' => $rev->getTitle()->getArticleID() ),
-                               __METHOD__,
-                               array(  'USE INDEX' => 'page_timestamp',
-                                       'ORDER BY' => 'rev_timestamp DESC',
-                                       'LIMIT' => $wgShowRollbackEditCount + 1 )
-                       );
-
-                       $editCount = 0;
-                       while( $row = $dbr->fetchObject( $res ) ) {
-                               if( $rev->getUserText() != $row->rev_user_text ) {
-                                       break;
-                               }
-                               $editCount++;
+                       if ( !is_numeric( $editCount ) ) {
+                               $editCount = self::getRollbackEditCount( $rev, false );
                        }
 
                        if( $editCount > $wgShowRollbackEditCount ) {
@@ -1863,13 +1931,19 @@ class Linker {
        /**
         * Returns HTML for the "templates used on this page" list.
         *
+        * Make an HTML list of templates, and then add a "More..." link at
+        * the bottom. If $more is null, do not add a "More..." link. If $more
+        * is a Title, make a link to that title and use it. If $more is a string,
+        * directly paste it in as the link.
+        *
         * @param $templates Array of templates from Article::getUsedTemplate
         * or similar
-        * @param $preview Boolean: whether this is for a preview
-        * @param $section Boolean: whether this is for a section edit
+        * @param bool $preview Whether this is for a preview
+        * @param bool $section Whether this is for a section edit
+        * @param Title|string|null $more A link for "More..." of the templates
         * @return String: HTML output
         */
-       public static function formatTemplates( $templates, $preview = false, $section = false ) {
+       public static function formatTemplates( $templates, $preview = false, $section = false, $more = null ) {
                wfProfileIn( __METHOD__ );
 
                $outText = '';
@@ -1926,9 +2000,16 @@ class Linker {
                                        . wfMessage( 'word-separator' )->escaped()
                                        . $protected . '</li>';
                        }
+
+                       if ( $more instanceof Title ) {
+                               $outText .= '<li>' . self::link( $more, wfMessage( 'moredotdotdot' ) ) . '</li>';
+                       } elseif ( $more ) {
+                               $outText .= "<li>$more</li>";
+                       }
+
                        $outText .= '</ul>';
                }
-               wfProfileOut( __METHOD__  );
+               wfProfileOut( __METHOD__ );
                return $outText;
        }
 
@@ -1954,7 +2035,7 @@ class Linker {
                        }
                        $outText .= '</ul>';
                }
-               wfProfileOut( __METHOD__  );
+               wfProfileOut( __METHOD__ );
                return $outText;
        }