Document makeExternalLink().
[lhc/web/wiklou.git] / includes / Linker.php
index e1ba276..c9d4db1 100644 (file)
@@ -190,15 +190,7 @@ class Linker {
                # If we don't know whether the page exists, let's find out.
                wfProfileIn( __METHOD__ . '-checkPageExistence' );
                if( !in_array( 'known', $options ) and !in_array( 'broken', $options ) ) {
-                       if( $target->getNamespace() == NS_SPECIAL ) {
-                               if( SpecialPage::exists( $target->getDbKey() ) ) {
-                                       $options []= 'known';
-                               } else {
-                                       $options []= 'broken';
-                               }
-                       } elseif( $target->isAlwaysKnown() or
-                       ($target->getPrefixedText() == '' and $target->getFragment() != '')
-                       or $target->exists() ) {
+                       if( $target->isKnown() ) {
                                $options []= 'known';
                        } else {
                                $options []= 'broken';
@@ -227,11 +219,8 @@ class Linker {
                }
 
                $ret = null;
-               if( wfRunHooks( 'LinkEnd', array( $this, $target, $options, &$text,
-               &$attribs, &$ret ) ) ) {
-                       $ret = Xml::openElement( 'a', $attribs )
-                               . $text
-                               . Xml::closeElement( 'a' );
+               if( wfRunHooks( 'LinkEnd', array( $this, $target, $options, &$text, &$attribs, &$ret ) ) ) {
+                       $ret = Xml::openElement( 'a', $attribs ) . $text . Xml::closeElement( 'a' );
                }
 
                wfProfileOut( __METHOD__ );
@@ -629,7 +618,7 @@ class Linker {
                $img = '';
                $success = wfRunHooks('LinkerMakeExternalImage', array( &$url, &$alt, &$img ) );
                if(!$success) {
-                       wfDebug("Hook LinkerMakeExternalImage changed the output of external image with url {$url} and alt text {$alt} to {$img}", true);
+                       wfDebug("Hook LinkerMakeExternalImage changed the output of external image with url {$url} and alt text {$alt} to {$img}\n", true);
                        return $img;
                }
                return Xml::element( 'img',
@@ -864,7 +853,7 @@ class Linker {
                } else {
                        if ( isset( $fp['manualthumb'] ) ) {
                                # Use manually specified thumbnail
-                               $manual_title = Title::makeTitleSafe( NS_IMAGE, $fp['manualthumb'] );
+                               $manual_title = Title::makeTitleSafe( NS_FILE, $fp['manualthumb'] );
                                if( $manual_title ) {
                                        $manual_img = wfFindFile( $manual_title );
                                        if ( $manual_img ) {
@@ -970,7 +959,7 @@ class Linker {
 
        /** @deprecated use Linker::makeMediaLinkObj() */
        function makeMediaLink( $name, $unused = '', $text = '', $time = false ) {
-               $nt = Title::makeTitleSafe( NS_IMAGE, $name );
+               $nt = Title::makeTitleSafe( NS_FILE, $name );
                return $this->makeMediaLinkObj( $nt, $text, $time );
        }
 
@@ -1018,22 +1007,37 @@ class Linker {
                  wfMsg( $key ) );
        }
 
-       /** @todo document */
+       /**
+        * Make an external link
+        * @param String $url URL to link to
+        * @param String $text text of link
+        * @param boolean $escape Do we escape the link text?
+        * @param String $linktype Type of external link. Gets added to the classes
+        * @param array $attribs Array of extra attributes to <a>
+        * 
+        * @TODO! @FIXME! This is a really crappy implementation. $linktype and 
+        * 'external' are mashed into the class attrib for the link (which is made
+        * into a string). Then, if we've got additional params in $attribs, we 
+        * add to it. People using this might want to change the classes (or other
+        * default link attributes), but passing $attribsText is just messy. Would 
+        * make a lot more sense to make put the classes into $attribs, let the 
+        * hook play with them, *then* expand it all at once. 
+        */
        function makeExternalLink( $url, $text, $escape = true, $linktype = '', $attribs = array() ) {
                $attribsText = $this->getExternalLinkAttributes( $url, $text, 'external ' . $linktype );
-               if ( $attribs ) {
-                       $attribsText .= Xml::expandAttributes( $attribs );
-               }
                $url = htmlspecialchars( $url );
                if( $escape ) {
                        $text = htmlspecialchars( $text );
                }
                $link = '';
-               $success = wfRunHooks('LinkerMakeExternalLink', array( &$url, &$text, &$link ) );
+               $success = wfRunHooks('LinkerMakeExternalLink', array( &$url, &$text, &$link, &$attribs, $linktype ) );
                if(!$success) {
-                       wfDebug("Hook LinkerMakeExternalLink changed the output of link with url {$url} and text {$text} to {$link}", true);
+                       wfDebug("Hook LinkerMakeExternalLink changed the output of link with url {$url} and text {$text} to {$link}\n", true);
                        return $link;
                }
+               if ( $attribs ) {
+                       $attribsText .= Xml::expandAttributes( $attribs );
+               }
                return '<a href="'.$url.'"'.$attribsText.'>'.$text.'</a>';
        }
 
@@ -1050,7 +1054,7 @@ class Linker {
                } else {
                        $page = Title::makeTitle( NS_USER, $userText );
                }
-               return $this->link( $page, htmlspecialchars( $userText ) );
+               return $this->link( $page, htmlspecialchars( $userText ), array( 'class' => 'mw-userlink' ) );
        }
 
        /**
@@ -1064,7 +1068,7 @@ class Linker {
         * @return string
         */
        public function userToolLinks( $userId, $userText, $redContribsWhenNoEdits = false, $flags = 0, $edits=null ) {
-               global $wgUser, $wgDisableAnonTalk, $wgSysopUserBans;
+               global $wgUser, $wgDisableAnonTalk, $wgSysopUserBans, $wgLang;
                $talkable = !( $wgDisableAnonTalk && 0 == $userId );
                $blockable = ( $wgSysopUserBans || 0 == $userId ) && !$flags & self::TOOL_LINKS_NOBLOCK;
 
@@ -1090,7 +1094,7 @@ class Linker {
                }
 
                if( $items ) {
-                       return ' (' . implode( ' | ', $items ) . ')';
+                       return ' <span class="mw-usertoollinks">(' . $wgLang->pipeList( $items ) . ')</span>';
                } else {
                        return '';
                }
@@ -1432,8 +1436,8 @@ class Linker {
                 . "</ul>\n</td></tr></table>"
                 . '<script type="' . $wgJsMimeType . '">'
                 . ' if (window.showTocToggle) {'
-                . ' var tocShowText = "' . wfEscapeJsString( wfMsg('showtoc') ) . '";'
-                . ' var tocHideText = "' . wfEscapeJsString( wfMsg('hidetoc') ) . '";'
+                . ' var tocShowText = "' . Xml::escapeJsString( wfMsg('showtoc') ) . '";'
+                . ' var tocHideText = "' . Xml::escapeJsString( wfMsg('hidetoc') ) . '";'
                 . ' showTocToggle();'
                 . ' } '
                 . "</script>\n";
@@ -1526,11 +1530,21 @@ class Linker {
         * @param string $anchor  The anchor to give the headline (the bit after the #)
         * @param string $text    The text of the header
         * @param string $link    HTML to add for the section edit link
+        * @param mixed  $legacyAnchor A second, optional anchor to give for
+        *   backward compatibility (false to omit)
         *
         * @return string HTML headline
         */
-       public function makeHeadline( $level, $attribs, $anchor, $text, $link ) {
-               return "<a name=\"$anchor\"></a><h$level$attribs$link <span class=\"mw-headline\">$text</span></h$level>";
+       public function makeHeadline( $level, $attribs, $anchor, $text, $link, $legacyAnchor = false ) {
+               $ret = "<a name=\"$anchor\" id=\"$anchor\"></a>"
+                       . "<h$level$attribs"
+                       . $link
+                       . " <span class=\"mw-headline\">$text</span>"
+                       . "</h$level>";
+               if ( $legacyAnchor !== false ) {
+                       $ret = "<a name=\"$legacyAnchor\" id=\"$legacyAnchor\"></a>$ret";
+               }
+               return $ret;
        }
 
        /**
@@ -1590,6 +1604,7 @@ class Linker {
                );
                if( $wgRequest->getBool( 'bot' ) ) {
                        $query['bot'] = '1';
+                       $query['hidediff'] = '1'; // bug 15999
                }
                $query['token'] = $wgUser->editToken( array( $title->getPrefixedText(),
                        $rev->getUserText() ) );
@@ -1607,12 +1622,9 @@ class Linker {
         * @param bool $section Whether this is for a section edit
         * @return string HTML output
         */
-       public function formatTemplates( $templates, $preview = false, $section = false) {
-               global $wgUser;
+       public function formatTemplates( $templates, $preview = false, $section = false ) {
                wfProfileIn( __METHOD__ );
 
-               $sk = $wgUser->getSkin();
-
                $outText = '';
                if ( count( $templates ) > 0 ) {
                        # Do a batch existence check
@@ -1631,7 +1643,7 @@ class Linker {
                        } else {
                                $outText .= wfMsgExt( 'templatesused', array( 'parse' ) );
                        }
-                       $outText .= '</div><ul>';
+                       $outText .= "</div><ul>\n";
 
                        usort( $templates, array( 'Title', 'compare' ) );
                        foreach ( $templates as $titleObj ) {
@@ -1644,11 +1656,11 @@ class Linker {
                                        $protected = '';
                                }
                                if( $titleObj->quickUserCan( 'edit' ) ) {
-                                       $editLink = $sk->makeLinkObj( $titleObj, wfMsg('editold'), 'action=edit' );
+                                       $editLink = $this->makeLinkObj( $titleObj, wfMsg('editlink'), 'action=edit' );
                                } else {
-                                       $editLink = $sk->makeLinkObj( $titleObj, wfMsg('viewsourceold'), 'action=edit' );
+                                       $editLink = $this->makeLinkObj( $titleObj, wfMsg('viewsourcelink'), 'action=edit' );
                                }
-                               $outText .= '<li>' . $sk->link( $titleObj ) . ' (' . $editLink . ') ' . $protected . '</li>';
+                               $outText .= '<li>' . $this->link( $titleObj ) . ' (' . $editLink . ') ' . $protected . '</li>';
                        }
                        $outText .= '</ul>';
                }
@@ -1663,21 +1675,19 @@ class Linker {
         * or similar
         * @return string HTML output
         */
-       public function formatHiddenCategories( $hiddencats) {
-               global $wgUser, $wgLang;
+       public function formatHiddenCategories( $hiddencats ) {
+               global $wgLang;
                wfProfileIn( __METHOD__ );
 
-               $sk = $wgUser->getSkin();
-
                $outText = '';
                if ( count( $hiddencats ) > 0 ) {
                        # Construct the HTML
                        $outText = '<div class="mw-hiddenCategoriesExplanation">';
                        $outText .= wfMsgExt( 'hiddencategories', array( 'parse' ), $wgLang->formatnum( count( $hiddencats ) ) );
-                       $outText .= '</div><ul>';
+                       $outText .= "</div><ul>\n";
 
                        foreach ( $hiddencats as $titleObj ) {
-                               $outText .= '<li>' . $sk->link( $titleObj, null, array(), array(), 'known' ) . '</li>'; # If it's hidden, it must exist - no need to check with a LinkBatch
+                               $outText .= '<li>' . $this->link( $titleObj, null, array(), array(), 'known' ) . "</li>\n"; # If it's hidden, it must exist - no need to check with a LinkBatch
                        }
                        $outText .= '</ul>';
                }
@@ -1698,38 +1708,37 @@ class Linker {
        }
 
        /**
-        * Given the id of an interface element, constructs the appropriate title
-        * and accesskey attributes from the system messages.  (Note, this is usu-
-        * ally the id but isn't always, because sometimes the accesskey needs to
-        * go on a different element than the id, for reverse-compatibility, etc.)
-        *
-        * @param string $name Id of the element, minus prefixes.
-        * @return string title and accesskey attributes, ready to drop in an
-        *   element (e.g., ' title="This does something [x]" accesskey="x"').
+        * @deprecated Returns raw bits of HTML, use titleAttrib() and accesskey()
         */
        public function tooltipAndAccesskey( $name ) {
-               wfProfileIn( __METHOD__ );
-               $attribs = array();
-
-               $tooltip = wfMsg( "tooltip-$name" );
-               if( !wfEmptyMsg( "tooltip-$name", $tooltip ) && $tooltip != '-' ) {
-                       // Compatibility: formerly some tooltips had [alt-.] hardcoded
-                       $tooltip = preg_replace( "/ ?\[alt-.\]$/", '', $tooltip );
-                       $attribs['title'] = $tooltip;
+               # FIXME: If Sanitizer::expandAttributes() treated "false" as "output
+               # no attribute" instead of "output '' as value for attribute", this
+               # would be three lines.
+               $attribs = array(
+                       'title' => $this->titleAttrib( $name, 'withaccess' ),
+                       'accesskey' => $this->accesskey( $name )
+               );
+               if ( $attribs['title'] === false ) {
+                       unset( $attribs['title'] );
                }
-
-               $accesskey = wfMsg( "accesskey-$name" );
-               if( $accesskey && $accesskey != '-' &&
-               !wfEmptyMsg( "accesskey-$name", $accesskey ) ) {
-                       if( isset( $attribs['title'] ) ) {
-                               $attribs['title'] .= " [$accesskey]";
-                       }
-                       $attribs['accesskey'] = $accesskey;
+               if ( $attribs['accesskey'] === false ) {
+                       unset( $attribs['accesskey'] );
                }
+               return Xml::expandAttributes( $attribs );
+       }
 
-               $ret = Xml::expandAttributes( $attribs );
-               wfProfileOut( __METHOD__ );
-               return $ret;
+       /** @deprecated Returns raw bits of HTML, use titleAttrib() */
+       public function tooltip( $name, $options = null ) {
+               # FIXME: If Sanitizer::expandAttributes() treated "false" as "output
+               # no attribute" instead of "output '' as value for attribute", this
+               # would be two lines.
+               $tooltip = $this->titleAttrib( $name, $options );
+               if ( $tooltip === false ) {
+                       return '';
+               }
+               return Xml::expandAttributes( array(
+                       'title' => $this->titleAttrib( $name, $options )
+               ) );
        }
 
        /**
@@ -1741,29 +1750,77 @@ class Linker {
         * @param string $name    Id of the element, minus prefixes.
         * @param mixed  $options null or the string 'withaccess' to add an access-
         *   key hint
-        * @return string title attribute, ready to drop in an element
-        * (e.g., ' title="This does something"').
+        * @return string Contents of the title attribute (which you must HTML-
+        *   escape), or false for no title attribute
         */
-       public function tooltip( $name, $options = null ) {
+       public function titleAttrib( $name, $options = null ) {
                wfProfileIn( __METHOD__ );
 
-               $attribs = array();
-
                $tooltip = wfMsg( "tooltip-$name" );
-               if( !wfEmptyMsg( "tooltip-$name", $tooltip ) && $tooltip != '-' ) {
-                       $attribs['title'] = $tooltip;
+               # Compatibility: formerly some tooltips had [alt-.] hardcoded
+               $tooltip = preg_replace( "/ ?\[alt-.\]$/", '', $tooltip );
+
+               # Message equal to '-' means suppress it.
+               if ( wfEmptyMsg( "tooltip-$name", $tooltip ) || $tooltip == '-' ) {
+                       $tooltip = false;
                }
 
-               if( isset( $attribs['title'] ) && $options == 'withaccess' ) {
-                       $accesskey = wfMsg( "accesskey-$name" );
-                       if( $accesskey && $accesskey != '-' &&
-                       !wfEmptyMsg( "accesskey-$name", $accesskey ) ) {
-                               $attribs['title'] .= " [$accesskey]";
+               if ( $options == 'withaccess' ) {
+                       $accesskey = $this->accesskey( $name );
+                       if( $accesskey !== false ) {
+                               if ( $tooltip === false || $tooltip === '' ) {
+                                       $tooltip = "[$accesskey]";
+                               } else {
+                                       $tooltip .= " [$accesskey]";
+                               }
                        }
                }
 
-               $ret = Xml::expandAttributes( $attribs );
                wfProfileOut( __METHOD__ );
-               return $ret;
+               return $tooltip;
+       }
+
+       /**
+        * Given the id of an interface element, constructs the appropriate
+        * accesskey attribute from the system messages.  (Note, this is usually
+        * the id but isn't always, because sometimes the accesskey needs to go on
+        * a different element than the id, for reverse-compatibility, etc.)
+        *
+        * @param string $name    Id of the element, minus prefixes.
+        * @return string Contents of the accesskey attribute (which you must HTML-
+        *   escape), or false for no accesskey attribute
+        */
+       public function accesskey( $name ) {
+               wfProfileIn( __METHOD__ );
+
+               $accesskey = wfMsg( "accesskey-$name" );
+
+               # FIXME: Per standard MW behavior, a value of '-' means to suppress the
+               # attribute, but this is broken for accesskey: that might be a useful
+               # value.
+               if( $accesskey != '' && $accesskey != '-' && !wfEmptyMsg( "accesskey-$name", $accesskey ) ) {
+                       wfProfileOut( __METHOD__ );
+                       return $accesskey;
+               }
+
+               wfProfileOut( __METHOD__ );
+               return false;
+       }
+       
+       /**
+        * Creates a (show/hide) link for deleting revisions/log entries
+        *
+        * @param array $query  Query parameters to be passed to link()
+        * @param bool $restricted  Set to true to use a <strong> instead of a <span>
+        *
+        * @return string HTML <a> link to Special:Revisiondelete, wrapped in a
+        * span to allow for customization of appearance with CSS
+        */
+       public function revDeleteLink( $query = array(), $restricted = false ) {
+               $sp = SpecialPage::getTitleFor( 'Revisiondelete' );
+               $text = wfMsgHtml( 'rev-delundel' );
+               $tag = $restricted ? 'strong' : 'span';
+               $link = $this->link( $sp, $text, array(), $query, array( 'known', 'noclasses' ) );
+               return Xml::tags( $tag, array( 'class' => 'mw-revdelundel-link' ), "($link)" );
        }
 }