* 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 );
}
/**
* @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
$title = $wgContLang->checkTitleEncoding( $title );
$title = preg_replace( '/[\\x00-\\x1f]/', ' ', $title );
- return $this->getLinkAttributesInternal( $title, $class, 'external' );
+ return $this->getLinkAttributesInternal( $title, $class );
}
/**
/**
* 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;
}
$ret = null;
if( wfRunHooks( 'LinkEnd', array( $this, $target, $options, &$text, &$attribs, &$ret ) ) ) {
- $ret = Xml::openElement( 'a', $attribs ) . $text . Xml::closeElement( 'a' );
+ $ret = Html::rawElement( 'a', $attribs, $text );
}
wfProfileOut( __METHOD__ );
/**
* Identical to link(), except $options defaults to 'known'.
*/
- public function linkKnown( $target, $text = null, $customAttribs = array(), $query = array(), $options = 'known' ) {
+ public function linkKnown( $target, $text = null, $customAttribs = array(), $query = array(), $options = array('known','noclasses') ) {
return $this->link( $target, $text, $customAttribs, $query, $options );
}
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',
+ return Html::element( 'img',
array(
'src' => $url,
'alt' => $alt ) );
# If thumbnail width has not been provided, it is set
# to the default user option as specified in Language*.php
if ( $fp['align'] == '' ) {
- $fp['align'] = $wgContLang->isRTL() ? 'left' : 'right';
+ $fp['align'] = $wgContLang->alignEnd();
}
return $prefix.$this->makeThumbLink2( $title, $file, $fp, $hp, $time, $query ).$postfix;
}
### HOTFIX. Instead of breaking, return empty string.
return $text;
} else {
- $img = wfFindFile( $title, $time );
+ $img = wfFindFile( $title, array( 'time' => $time ) );
if( $img ) {
$url = $img->getURL();
$class = 'internal';
* 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 );
return $link;
}
if ( $attribs ) {
- $attribsText .= Xml::expandAttributes( $attribs );
+ $attribsText .= Html::expandAttributes( $attribs );
}
return '<a href="'.$url.'"'.$attribsText.'>'.$text.'</a>';
}
# 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;
* @param string $comment Text to format links in
* @return string
*/
- public function formatLinksInComment( $comment ) {
- return preg_replace_callback(
+ public function formatLinksInComment( $comment, $title = null, $local = false ) {
+ $this->commentContextTitle = $title;
+ $this->commentLocal = $local;
+ $html = preg_replace_callback(
'/\[\[:?(.*?)(\|(.*?))*\]\]([^[]*)/',
array( $this, 'formatLinksInCommentCallback' ),
$comment );
+ unset( $this->commentContextTitle );
+ unset( $this->commentLocal );
+ return $html;
}
protected function formatLinksInCommentCallback( $match ) {
$text = $match[1];
}
$submatch = array();
+ $thelink = null;
if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
# Media link; trail not supported.
$linkRegexp = '/\[\[(.*?)\]\]/';
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
/** @todo document */
function tocList($toc) {
- global $wgJsMimeType;
$title = wfMsgHtml('toc') ;
return
- '<table id="toc" class="toc" summary="' . $title .'"><tr><td>'
+ '<table id="toc" class="toc"><tr><td>'
. '<div id="toctitle"><h2>' . $title . "</h2></div>\n"
. $toc
# no trailing newline, script should not be wrapped in a
# paragraph
. "</ul>\n</td></tr></table>"
- . '<script type="' . $wgJsMimeType . '">'
- . ' if (window.showTocToggle) {'
- . ' var tocShowText = "' . Xml::escapeJsString( wfMsg('showtoc') ) . '";'
- . ' var tocHideText = "' . Xml::escapeJsString( wfMsg('hidetoc') ) . '";'
- . ' showTocToggle();'
- . ' } '
- . "</script>\n";
+ . Html::inlineScript(
+ 'if (window.showTocToggle) {'
+ . ' var tocShowText = "' . Xml::escapeJsString( wfMsg('showtoc') ) . '";'
+ . ' var tocHideText = "' . Xml::escapeJsString( wfMsg('hidetoc') ) . '";'
+ . ' showTocToggle();'
+ . ' } ' )
+ . "\n";
}
/**
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
* @return string HTML headline
*/
public function makeHeadline( $level, $attribs, $anchor, $text, $link, $legacyAnchor = false ) {
- $ret = "<a name=\"$anchor\" id=\"$anchor\"></a>"
- . "<h$level$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 name=\"$legacyAnchor\" id=\"$legacyAnchor\"></a>$ret";
+ $ret = "<a id=\"$legacyAnchor\"></a>$ret";
}
return $ret;
}
if ( $valign ) {
$frameParams['valign'] = $valign;
}
- $file = wfFindFile( $title, $time );
+ $file = wfFindFile( $title, array( 'time' => $time ) );
return $this->makeImageLink2( $title, $file, $frameParams, $handlerParams, $time );
}
* @deprecated Returns raw bits of HTML, use titleAttrib() and accesskey()
*/
public function tooltipAndAccesskey( $name ) {
+ global $wgDisableTooltipsAndAccesskeys;
+ if ($wgDisableTooltipsAndAccesskeys)
+ return array();
# FIXME: If Sanitizer::expandAttributes() treated "false" as "output
# no attribute" instead of "output '' as value for attribute", this
# would be three lines.
/** @deprecated Returns raw bits of HTML, use titleAttrib() */
public function tooltip( $name, $options = null ) {
+ global $wgDisableTooltipsAndAccesskeys;
+ if ($wgDisableTooltipsAndAccesskeys)
+ return array();
# FIXME: If Sanitizer::expandAttributes() treated "false" as "output
# no attribute" instead of "output '' as value for attribute", this
# would be two lines.