fix typo in comment
[lhc/web/wiklou.git] / includes / Linker.php
index 02e4790..bcd23a7 100644 (file)
@@ -21,13 +21,11 @@ class Linker {
         * Get the appropriate HTML attributes to add to the "a" element of an ex-
         * ternal link, as created by [wikisyntax].
         *
-        * @param string $title  The (unescaped) title text for the link
-        * @param string $unused Unused
         * @param string $class  The contents of the class attribute; if an empty
         *   string is passed, which is the default value, defaults to 'external'.
         */
-       function getExternalLinkAttributes( $title, $unused = null, $class='' ) {
-               return $this->getLinkAttributesInternal( $title, $class, 'external' );
+       function getExternalLinkAttributes( $class = 'external' ) {
+               return $this->getLinkAttributesInternal( '', $class );
        }
 
        /**
@@ -40,7 +38,7 @@ class Linker {
         * @param string $class  The contents of the class attribute; if an empty
         *   string is passed, which is the default value, defaults to 'external'.
         */
-       function getInterwikiLinkAttributes( $title, $unused = null, $class='' ) {
+       function getInterwikiLinkAttributes( $title, $unused = null, $class = 'external' ) {
                global $wgContLang;
 
                # FIXME: We have a whole bunch of handling here that doesn't happen in
@@ -49,7 +47,7 @@ class Linker {
                $title = $wgContLang->checkTitleEncoding( $title );
                $title = preg_replace( '/[\\x00-\\x1f]/', ' ', $title );
 
-               return $this->getLinkAttributesInternal( $title, $class, 'external' );
+               return $this->getLinkAttributesInternal( $title, $class );
        }
 
        /**
@@ -87,20 +85,16 @@ class Linker {
        /**
         * Common code for getLinkAttributesX functions
         */
-       private function getLinkAttributesInternal( $title, $class, $classDefault = false ) {
+       private function getLinkAttributesInternal( $title, $class ) {
                $title = htmlspecialchars( $title );
-               if( $class === '' and $classDefault !== false ) {
-                       # FIXME: Parameter defaults the hard way!  We should just have
-                       # $class = 'external' or whatever as the default in the externally-
-                       # exposed functions, not $class = ''.
-                       $class = $classDefault;
-               }
                $class = htmlspecialchars( $class );
                $r = '';
-               if( $class !== '' ) {
+               if ( $class != '' ) {
                        $r .= " class=\"$class\"";
                }
-               $r .= " title=\"$title\"";
+               if ( $title != '') {
+                       $r .= " title=\"$title\"";
+               }
                return $r;
        }
 
@@ -747,7 +741,7 @@ class Linker {
         * 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 );
+               $attribsText = $this->getExternalLinkAttributes( 'external ' . $linktype );
                $url = htmlspecialchars( $url );
                if( $escape ) {
                        $text = htmlspecialchars( $text );
@@ -928,7 +922,7 @@ class Linker {
 
                # Render autocomments and make links:
                $comment = $this->formatAutoComments( $comment, $title, $local );
-               $comment = $this->formatLinksInComment( $comment );
+               $comment = $this->formatLinksInComment( $comment, $title, $local );
 
                wfProfileOut( __METHOD__ );
                return $comment;
@@ -1015,11 +1009,28 @@ class Linker {
         * @param string $comment Text to format links in
         * @return string
         */
-       public function formatLinksInComment( $comment ) {
-               return preg_replace_callback(
-                       '/\[\[:?(.*?)(\|(.*?))*\]\]([^[]*)/',
-                       array( $this, 'formatLinksInCommentCallback' ),
-                       $comment );
+       public function formatLinksInComment( $comment, $title = null, $local = false ) {
+               $this->commentContextTitle = $title;
+               $this->commentLocal = $local;
+               # Borrowed from Parser::replaceInternalLinks2
+               $parts = StringUtils::explode( '[[', ' ' . $comment );
+               $start = $parts->current();
+               $parts->next();
+               $line = $parts->current();
+               $html = substr( $start, 1 );
+               for ( ; $line !== false && $line !== null ; $parts->next(), $line = $parts->current() ) {                       
+                       $linked = preg_replace_callback(
+                               '/^:?(.*?)(\|(.*?))*\]\]([^[]*)/',
+                               array( $this, 'formatLinksInCommentCallback' ),
+                               $line, -1, $count );
+                       if( !$count ) { // No valid link found, put the brackets back
+                               $linked = '[[' . $linked;
+                       }
+                       $html .= $linked;
+               }
+               unset( $this->commentContextTitle );
+               unset( $this->commentLocal );
+               return $html;
        }
 
        protected function formatLinksInCommentCallback( $match ) {
@@ -1042,9 +1053,10 @@ class Linker {
                        $text = $match[1];
                }
                $submatch = array();
+               $thelink = null;
                if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
                        # Media link; trail not supported.
-                       $linkRegexp = '/\[\[(.*?)\]\]/';
+                       $linkRegexp = '/^(.*?)\]\]/';
                        $title = Title::makeTitleSafe( NS_FILE, $submatch[1] );
                        $thelink = $this->makeMediaLinkObj( $title, $text );
                } else {
@@ -1054,19 +1066,107 @@ class Linker {
                        } else {
                                $trail = "";
                        }
-                       $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
+                       $linkRegexp = '/^(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
                        if (isset($match[1][0]) && $match[1][0] == ':')
                                $match[1] = substr($match[1], 1);
                        list( $inside, $trail ) = Linker::splitTrail( $trail );
-                       $thelink = $this->link(
-                               Title::newFromText( $match[1] ),
-                               $text . $inside
-                       ) . $trail;
+                       
+                       $linkText = $text;
+                       $linkTarget = Linker::normalizeSubpageLink( $this->commentContextTitle,
+                               $match[1], $linkText );
+                       
+                       $target = Title::newFromText( $linkTarget );
+                       if( $target ) {
+                               if( $target->getText() == '' && !$this->commentLocal && $this->commentContextTitle ) {
+                                       $newTarget = clone( $this->commentContextTitle );
+                                       $newTarget->setFragment( '#' . $target->getFragment() );
+                                       $target = $newTarget;
+                               }
+                               $thelink = $this->link(
+                                       $target,
+                                       $linkText . $inside
+                               ) . $trail;
+                       }
+               }
+               if( $thelink ) {
+                       // If the link is still valid, go ahead and replace it in!
+                       $comment = preg_replace( $linkRegexp, StringUtils::escapeRegexReplacement( $thelink ), $comment, 1 );
                }
-               $comment = preg_replace( $linkRegexp, StringUtils::escapeRegexReplacement( $thelink ), $comment, 1 );
 
                return $comment;
        }
+       
+       static function normalizeSubpageLink( $contextTitle, $target, &$text ) {
+               # Valid link forms:
+               # Foobar -- normal
+               # :Foobar -- override special treatment of prefix (images, language links)
+               # /Foobar -- convert to CurrentPage/Foobar
+               # /Foobar/ -- convert to CurrentPage/Foobar, strip the initial / from text
+               # ../ -- convert to CurrentPage, from CurrentPage/CurrentSubPage
+               # ../Foobar -- convert to CurrentPage/Foobar, from CurrentPage/CurrentSubPage
+
+               wfProfileIn( __METHOD__ );
+               $ret = $target; # default return value is no change
+
+               # Some namespaces don't allow subpages,
+               # so only perform processing if subpages are allowed
+               if( $contextTitle && MWNamespace::hasSubpages( $contextTitle->getNamespace() ) ) {
+                       $hash = strpos( $target, '#' );
+                       if( $hash !== false ) {
+                               $suffix = substr( $target, $hash );
+                               $target = substr( $target, 0, $hash );
+                       } else {
+                               $suffix = '';
+                       }
+                       # bug 7425
+                       $target = trim( $target );
+                       # Look at the first character
+                       if( $target != '' && $target{0} === '/' ) {
+                               # / at end means we don't want the slash to be shown
+                               $m = array();
+                               $trailingSlashes = preg_match_all( '%(/+)$%', $target, $m );
+                               if( $trailingSlashes ) {
+                                       $noslash = $target = substr( $target, 1, -strlen($m[0][0]) );
+                               } else {
+                                       $noslash = substr( $target, 1 );
+                               }
+
+                               $ret = $contextTitle->getPrefixedText(). '/' . trim($noslash) . $suffix;
+                               if( '' === $text ) {
+                                       $text = $target . $suffix;
+                               } # this might be changed for ugliness reasons
+                       } else {
+                               # check for .. subpage backlinks
+                               $dotdotcount = 0;
+                               $nodotdot = $target;
+                               while( strncmp( $nodotdot, "../", 3 ) == 0 ) {
+                                       ++$dotdotcount;
+                                       $nodotdot = substr( $nodotdot, 3 );
+                               }
+                               if($dotdotcount > 0) {
+                                       $exploded = explode( '/', $contextTitle->GetPrefixedText() );
+                                       if( count( $exploded ) > $dotdotcount ) { # not allowed to go below top level page
+                                               $ret = implode( '/', array_slice( $exploded, 0, -$dotdotcount ) );
+                                               # / at the end means don't show full path
+                                               if( substr( $nodotdot, -1, 1 ) === '/' ) {
+                                                       $nodotdot = substr( $nodotdot, 0, -1 );
+                                                       if( '' === $text ) {
+                                                               $text = $nodotdot . $suffix;
+                                                       }
+                                               }
+                                               $nodotdot = trim( $nodotdot );
+                                               if( $nodotdot != '' ) {
+                                                       $ret .= '/' . $nodotdot;
+                                               }
+                                               $ret .= $suffix;
+                                       }
+                               }
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $ret;
+       }
 
        /**
         * Wrap a comment in standard punctuation and formatting if
@@ -1186,7 +1286,7 @@ class Linker {
                foreach ( $tree as $section ) {
                        if ( $section['toclevel'] > $lastLevel )
                                $toc .= $this->tocIndent();
-                       else if ( $secton['toclevel'] < $lastLevel )
+                       else if ( $section['toclevel'] < $lastLevel )
                                $toc .= $this->tocUnindent(
                                        $lastLevel - $section['toclevel'] );
                        else
@@ -1266,9 +1366,9 @@ class Linker {
         * @return string HTML headline
         */
        public function makeHeadline( $level, $attribs, $anchor, $text, $link, $legacyAnchor = false ) {
-               $ret = "<h$level id=\"$anchor\"$attribs"
+               $ret = "<h$level$attribs"
                        . $link
-                       . " <span class=\"mw-headline\">$text</span>"
+                       . " <span class=\"mw-headline\" id=\"$anchor\">$text</span>"
                        . "</h$level>";
                if ( $legacyAnchor !== false ) {
                        $ret = "<a id=\"$legacyAnchor\"></a>$ret";