API: Page prop=revisions by rev_id or (rev_page, rev_id), depending on mode, because...
[lhc/web/wiklou.git] / includes / Linker.php
index bc9d12c..9b52671 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',
@@ -699,8 +688,8 @@ class Linker {
         *                          bottom, text-bottom)
         *          alt             Alternate text for image (i.e. alt attribute). Plain text.
         *          caption         HTML for image caption.
-        *          click-url       URL to link to
-        *          click-title     Title object to link to
+        *          link-url        URL to link to
+        *          link-title      Title object to link to
         *          no-link         Boolean, suppress description link
         *
         * @param array $handlerParams Associative array of media handler parameters, to be passed
@@ -730,11 +719,12 @@ class Linker {
                $page = isset( $hp['page'] ) ? $hp['page'] : false;
                if ( !isset( $fp['align'] ) ) $fp['align'] = '';
                if ( !isset( $fp['alt'] ) ) $fp['alt'] = '';
+               # Backward compatibility, title used to always be equal to alt text
+               if ( !isset( $fp['title'] ) ) $fp['title'] = $fp['alt'];
 
                $prefix = $postfix = '';
 
-               if ( 'center' == $fp['align'] )
-               {
+               if ( 'center' == $fp['align'] ) {
                        $prefix  = '<div class="center">';
                        $postfix = '</div>';
                        $fp['align']   = 'none';
@@ -765,7 +755,6 @@ class Linker {
                }
 
                if ( isset( $fp['thumbnail'] ) || isset( $fp['manualthumb'] ) || isset( $fp['framed'] ) ) {
-
                        # Create a thumbnail. Alignment depends on language
                        # writing direction, # right aligned for left-to-right-
                        # languages ("Western languages"), left-aligned
@@ -800,12 +789,13 @@ class Linker {
                } else {
                        $params = array(
                                'alt' => $fp['alt'],
+                               'title' => $fp['title'],
                                'valign' => isset( $fp['valign'] ) ? $fp['valign'] : false ,
                                'img-class' => isset( $fp['border'] ) ? 'thumbborder' : false );
-                       if ( !empty( $fp['click-url'] ) ) {
-                               $params['custom-url-link'] = $fp['click-url'];
-                       } elseif ( !empty( $fp['click-title'] ) ) {
-                               $params['custom-title-link'] = $fp['click-title'];
+                       if ( !empty( $fp['link-url'] ) ) {
+                               $params['custom-url-link'] = $fp['link-url'];
+                       } elseif ( !empty( $fp['link-title'] ) ) {
+                               $params['custom-title-link'] = $fp['link-title'];
                        } elseif ( !empty( $fp['no-link'] ) ) {
                                // No link
                        } else {
@@ -848,6 +838,8 @@ class Linker {
                $page = isset( $hp['page'] ) ? $hp['page'] : false;
                if ( !isset( $fp['align'] ) ) $fp['align'] = 'right';
                if ( !isset( $fp['alt'] ) ) $fp['alt'] = '';
+               # Backward compatibility, title used to always be equal to alt text
+               if ( !isset( $fp['title'] ) ) $fp['title'] = $fp['alt'];
                if ( !isset( $fp['caption'] ) ) $fp['caption'] = '';
 
                if ( empty( $hp['width'] ) ) {
@@ -861,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 ) {
@@ -907,6 +899,7 @@ class Linker {
                } else {
                        $s .= $thumb->toHtml( array(
                                'alt' => $fp['alt'],
+                               'title' => $fp['title'],
                                'img-class' => 'thumbimage',
                                'desc-link' => true,
                                'desc-query' => $query ) );
@@ -966,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 );
        }
 
@@ -1027,7 +1020,7 @@ class Linker {
                $link = '';
                $success = wfRunHooks('LinkerMakeExternalLink', array( &$url, &$text, &$link ) );
                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;
                }
                return '<a href="'.$url.'"'.$attribsText.'>'.$text.'</a>';
@@ -1046,7 +1039,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' ) );
        }
 
        /**
@@ -1060,7 +1053,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;
 
@@ -1086,7 +1079,7 @@ class Linker {
                }
 
                if( $items ) {
-                       return ' (' . implode( ' | ', $items ) . ')';
+                       return ' <span class="mw-usertoollinks">(' . $wgLang->pipeList( $items ) . ')</span>';
                } else {
                        return '';
                }
@@ -1428,8 +1421,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";
@@ -1522,11 +1515,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;
        }
 
        /**
@@ -1586,6 +1589,7 @@ class Linker {
                );
                if( $wgRequest->getBool( 'bot' ) ) {
                        $query['bot'] = '1';
+                       $query['hidediff'] = '1'; // bug 15999
                }
                $query['token'] = $wgUser->editToken( array( $title->getPrefixedText(),
                        $rev->getUserText() ) );
@@ -1603,12 +1607,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
@@ -1627,7 +1628,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 ) {
@@ -1639,7 +1640,12 @@ class Linker {
                                } else {
                                        $protected = '';
                                }
-                               $outText .= '<li>' . $sk->link( $titleObj ) . ' ' . $protected . '</li>';
+                               if( $titleObj->quickUserCan( 'edit' ) ) {
+                                       $editLink = $this->makeLinkObj( $titleObj, wfMsg('editlink'), 'action=edit' );
+                               } else {
+                                       $editLink = $this->makeLinkObj( $titleObj, wfMsg('viewsourcelink'), 'action=edit' );
+                               }
+                               $outText .= '<li>' . $this->link( $titleObj ) . ' (' . $editLink . ') ' . $protected . '</li>';
                        }
                        $outText .= '</ul>';
                }
@@ -1654,21 +1660,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>';
                }
@@ -1689,38 +1693,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 )
+               ) );
        }
 
        /**
@@ -1732,29 +1735,81 @@ 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 = 'span';
+               if( $restricted )
+                       $tag = 'strong';
+               $link = $this->link( $sp, $text, array(), $query, array( 'known', 'noclasses' ) );
+               return Xml::tags( $tag, array( 'class' => 'mw-revdelundel-link' ), "($link)" );
        }
 }