if ( $t->isRedirect() ) {
# Page is a redirect
$colour = 'mw-redirect';
- } elseif ( $threshold > 0 && $t->getLength() < $threshold && MWNamespace::isContent( $t->getNamespace() ) ) {
+ } elseif ( $threshold > 0 &&
+ $t->exists() && $t->getLength() < $threshold &&
+ MWNamespace::isContent( $t->getNamespace() ) ) {
# Page is a stub
$colour = 'stub';
}
* the link text. This is raw HTML and will not be escaped. If null,
* defaults to the prefixed text of the Title; or if the Title is just a
* fragment, the contents of the fragment.
- * @param $query array The query string to append to the URL
- * you're linking to, in key => value array form. Query keys and values
- * will be URL-encoded.
* @param $customAttribs array A key => value array of extra HTML attri-
* butes, such as title and class. (href is ignored.) Classes will be
* merged with the default classes, while other attributes will replace
* default attributes. All passed attribute values will be HTML-escaped.
* A false attribute value means to suppress that attribute.
+ * @param $query array The query string to append to the URL
+ * you're linking to, in key => value array form. Query keys and values
+ * will be URL-encoded.
* @param $options mixed String or array of strings:
* 'known': Page is known to exist, so don't check if it does.
* 'broken': Page is known not to exist, so don't check if it does.
* "stub", "mw-redirect", "extiw"). Only use the class attribute
* provided, if any, so you get a simple blue link with no funny i-
* cons.
+ * 'forcearticlepath': Use the article path always, even with a querystring.
+ * Has compatibility issues on some setups, so avoid wherever possible.
* @return string HTML <a> attribute
*/
public function link( $target, $text = null, $customAttribs = array(), $query = array(), $options = array() ) {
wfProfileIn( __METHOD__ );
+ if( !$target instanceof Title ) {
+ return "<!-- ERROR -->$text";
+ }
+ $options = (array)$options;
+
$ret = null;
if( !wfRunHooks( 'LinkBegin', array( $this, $target, &$text,
&$customAttribs, &$query, &$options, &$ret ) ) ) {
return $ret;
}
- if( !$target instanceof Title ) {
- throw new MWException( 'Linker::link passed invalid target' );
- }
- $options = (array)$options;
-
# Normalize the Title if it's a special page
$target = $this->normaliseSpecialPage( $target );
# 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';
}
wfProfileOut( __METHOD__ . '-checkPageExistence' );
+ $oldquery = array();
+ if( in_array( "forcearticlepath", $options ) && $query ){
+ $oldquery = $query;
+ $query = array();
+ }
+
# Note: we want the href attribute first, for prettiness.
$attribs = array( 'href' => $this->linkUrl( $target, $query, $options ) );
+ if( in_array( 'forcearticlepath', $options ) && $oldquery ){
+ $attribs['href'] = wfAppendQuery( $attribs['href'], wfArrayToCgi( $oldquery ) );
+ }
+
$attribs = array_merge(
$attribs,
$this->linkAttribs( $target, $customAttribs, $options )
}
$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__ );
} elseif( $target->isContentPage() ) {
# Check for stub.
$threshold = $wgUser->getOption( 'stubthreshold' );
- if( $threshold > 0 and $target->getLength() < $threshold ) {
+ if( $threshold > 0 and $target->exists() and $target->getLength() < $threshold ) {
$classes[] = 'stub';
}
}
}
private function linkText( $target ) {
+ # We might be passed a non-Title by make*LinkObj(). Fail gracefully.
+ if( !$target instanceof Title ) {
+ return '';
+ }
+
# If the target is just a fragment, with no title, we return the frag-
# ment text. Otherwise, we return the title text itself.
if( $target->getPrefixedText() === '' and $target->getFragment() !== '' ) {
* the end of the link.
* @param $prefix String: optional prefix. As trail, only before instead of after.
*/
- function makeLinkObj( Title $nt, $text= '', $query = '', $trail = '', $prefix = '' ) {
+ function makeLinkObj( $nt, $text= '', $query = '', $trail = '', $prefix = '' ) {
global $wgUser;
wfProfileIn( __METHOD__ );
* @param $style String: style to apply - if empty, use getInternalLinkAttributesObj instead
* @return the a-element
*/
- function makeKnownLinkObj( Title $title, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '', $style = '' ) {
+ function makeKnownLinkObj( $title, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '', $style = '' ) {
wfProfileIn( __METHOD__ );
if ( $text == '' ) {
* be included in the link text. Other characters will be appended after
* the end of the link.
*/
- function makeBrokenLinkObj( Title $title, $text = '', $query = '', $trail = '', $prefix = '' ) {
+ function makeBrokenLinkObj( $title, $text = '', $query = '', $trail = '', $prefix = '' ) {
wfProfileIn( __METHOD__ );
list( $inside, $trail ) = Linker::splitTrail( $trail );
* bottom, text-bottom)
* alt Alternate text for image (i.e. alt attribute). Plain text.
* caption HTML for image caption.
+ * 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
* to transform(). Typical keys are "width" and "page".
$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';
}
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
if ( !$thumb ) {
$s = $this->makeBrokenImageLinkObj( $title, '', '', '', '', $time==true );
} else {
- $s = $thumb->toHtml( array(
- 'desc-link' => true,
- 'desc-query' => $query,
+ $params = array(
'alt' => $fp['alt'],
+ 'title' => $fp['title'],
'valign' => isset( $fp['valign'] ) ? $fp['valign'] : false ,
- 'img-class' => isset( $fp['border'] ) ? 'thumbborder' : false ) );
+ 'img-class' => isset( $fp['border'] ) ? 'thumbborder' : false );
+ 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 {
+ $params['desc-link'] = true;
+ $params['desc-query'] = $query;
+ }
+
+ $s = $thumb->toHtml( $params );
}
if ( '' != $fp['align'] ) {
- $s = "<div class=\"float{$fp['align']}\"><span>{$s}</span></div>";
+ $s = "<div class=\"float{$fp['align']}\">{$s}</div>";
}
return str_replace("\n", ' ',$prefix.$s.$postfix);
}
$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'] ) ) {
} 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 ) {
} else {
$s .= $thumb->toHtml( array(
'alt' => $fp['alt'],
+ 'title' => $fp['title'],
'img-class' => 'thumbimage',
'desc-link' => true,
'desc-query' => $query ) );
/** @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 );
}
}
/** @todo document */
- function makeExternalLink( $url, $text, $escape = true, $linktype = '', $ns = null ) {
- $style = $this->getExternalLinkAttributes( $url, $text, 'external ' . $linktype );
- global $wgNoFollowLinks, $wgNoFollowNsExceptions;
- if( $wgNoFollowLinks && !(isset($ns) && in_array($ns, $wgNoFollowNsExceptions)) ) {
- $style .= ' rel="nofollow"';
+ 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 ) {
wfDebug("Hook LinkerMakeExternalLink changed the output of link with url {$url} and text {$text} to {$link}", true);
return $link;
}
- return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
+ return '<a href="'.$url.'"'.$attribsText.'>'.$text.'</a>';
}
/**
} else {
$page = Title::makeTitle( NS_USER, $userText );
}
- return $this->link( $page, htmlspecialchars( $userText ) );
+ return $this->link( $page, htmlspecialchars( $userText ), array( 'class' => 'mw-userlink' ) );
}
/**
}
if( $items ) {
- return ' (' . implode( ' | ', $items ) . ')';
+ return ' <span class="mw-usertoollinks">(' . implode( ' | ', $items ) . ')</span>';
} else {
return '';
}
if( $rev->isDeleted( Revision::DELETED_USER ) && $isPublic ) {
$link = wfMsgHtml( 'rev-deleted-user' );
} else if( $rev->userCan( Revision::DELETED_USER ) ) {
- $link = $this->userLink( $rev->getRawUser(), $rev->getRawUserText() );
+ $link = $this->userLink( $rev->getUser( Revision::FOR_THIS_USER ),
+ $rev->getUserText( Revision::FOR_THIS_USER ) );
} else {
$link = wfMsgHtml( 'rev-deleted-user' );
}
if( $rev->isDeleted( Revision::DELETED_USER ) && $isPublic ) {
$link = wfMsgHtml( 'rev-deleted-user' );
} else if( $rev->userCan( Revision::DELETED_USER ) ) {
- $link = $this->userLink( $rev->getRawUser(), $rev->getRawUserText() ) .
- ' ' . $this->userToolLinks( $rev->getRawUser(), $rev->getRawUserText() );
+ $userId = $rev->getUser( Revision::FOR_THIS_USER );
+ $userText = $rev->getUserText( Revision::FOR_THIS_USER );
+ $link = $this->userLink( $userId, $userText ) .
+ ' ' . $this->userToolLinks( $userId, $userText );
} else {
$link = wfMsgHtml( 'rev-deleted-user' );
}
# Sanitize text a bit:
$comment = str_replace( "\n", " ", $comment );
- $comment = htmlspecialchars( $comment );
+ # Allow HTML entities (for bug 13815)
+ $comment = Sanitizer::escapeHtmlAllowEntities( $comment );
# Render autocomments and make links:
$comment = $this->formatAutoComments( $comment, $title, $local );
* @todo Document the $local parameter.
*/
private function formatAutocomments( $comment, $title = null, $local = false ) {
- $match = array();
- while (preg_match('!(.*)/\*\s*(.*?)\s*\*/(.*)!', $comment,$match)) {
- $pre=$match[1];
- $auto=$match[2];
- $post=$match[3];
- $link='';
- if( $title ) {
- $section = $auto;
-
- # Generate a valid anchor name from the section title.
- # Hackish, but should generally work - we strip wiki
- # syntax, including the magic [[: that is used to
- # "link rather than show" in case of images and
- # interlanguage links.
- $section = str_replace( '[[:', '', $section );
- $section = str_replace( '[[', '', $section );
- $section = str_replace( ']]', '', $section );
- if ( $local ) {
- $sectionTitle = Title::newFromText( '#' . $section );
- } else {
- $sectionTitle = clone( $title );
- $sectionTitle->mFragment = $section;
- }
+ // Bah!
+ $this->autocommentTitle = $title;
+ $this->autocommentLocal = $local;
+ $comment = preg_replace_callback(
+ '!(.*)/\*\s*(.*?)\s*\*/(.*)!',
+ array( $this, 'formatAutocommentsCallback' ),
+ $comment );
+ unset( $this->autocommentTitle );
+ unset( $this->autocommentLocal );
+ return $comment;
+ }
+
+ private function formatAutocommentsCallback( $match ) {
+ $title = $this->autocommentTitle;
+ $local = $this->autocommentLocal;
+
+ $pre=$match[1];
+ $auto=$match[2];
+ $post=$match[3];
+ $link='';
+ if( $title ) {
+ $section = $auto;
+
+ # Generate a valid anchor name from the section title.
+ # Hackish, but should generally work - we strip wiki
+ # syntax, including the magic [[: that is used to
+ # "link rather than show" in case of images and
+ # interlanguage links.
+ $section = str_replace( '[[:', '', $section );
+ $section = str_replace( '[[', '', $section );
+ $section = str_replace( ']]', '', $section );
+ if ( $local ) {
+ $sectionTitle = Title::newFromText( '#' . $section );
+ } else {
+ $sectionTitle = Title::makeTitleSafe( $title->getNamespace(),
+ $title->getDBkey(), $section );
+ }
+ if ( $sectionTitle ) {
$link = $this->link( $sectionTitle,
wfMsgForContent( 'sectionlink' ), array(), array(),
'noclasses' );
+ } else {
+ $link = '';
}
- $auto = $link . $auto;
- if( $pre ) {
- # written summary $presep autocomment (summary /* section */)
- $auto = wfMsgExt( 'autocomment-prefix', array( 'escapenoentities', 'content' ) ) . $auto;
- }
- if( $post ) {
- # autocomment $postsep written summary (/* section */ summary)
- $auto .= wfMsgExt( 'colon-separator', array( 'escapenoentities', 'content' ) );
- }
- $auto = '<span class="autocomment">' . $auto . '</span>';
- $comment = $pre . $auto . $post;
}
-
+ $auto = "$link$auto";
+ if( $pre ) {
+ # written summary $presep autocomment (summary /* section */)
+ $auto = wfMsgExt( 'autocomment-prefix', array( 'escapenoentities', 'content' ) ) . $auto;
+ }
+ if( $post ) {
+ # autocomment $postsep written summary (/* section */ summary)
+ $auto .= wfMsgExt( 'colon-separator', array( 'escapenoentities', 'content' ) );
+ }
+ $auto = '<span class="autocomment">' . $auto . '</span>';
+ $comment = $pre . $auto . $post;
return $comment;
}
if( $rev->isDeleted( Revision::DELETED_COMMENT ) && $isPublic ) {
$block = " <span class=\"comment\">" . wfMsgHtml( 'rev-deleted-comment' ) . "</span>";
} else if( $rev->userCan( Revision::DELETED_COMMENT ) ) {
- $block = $this->commentBlock( $rev->getRawComment(), $rev->getTitle(), $local );
+ $block = $this->commentBlock( $rev->getComment( Revision::FOR_THIS_USER ),
+ $rev->getTitle(), $local );
} else {
$block = " <span class=\"comment\">" . wfMsgHtml( 'rev-deleted-comment' ) . "</span>";
}
. "</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";
if( !is_null( $tooltip ) ) {
$attribs['title'] = wfMsg( 'editsectionhint', $tooltip );
}
- $url = $this->link( $nt, wfMsg('editsection'),
+ $link = $this->link( $nt, wfMsg('editsection'),
$attribs,
array( 'action' => 'edit', 'section' => $section ),
array( 'noclasses', 'known' )
$attribs = " title=\"$attribs\"";
}
$result = null;
- wfRunHooks( 'EditSectionLink', array( &$this, $nt, $section, $attribs, $url, &$result ) );
+ wfRunHooks( 'EditSectionLink', array( &$this, $nt, $section, $attribs, $link, &$result ) );
if( !is_null( $result ) ) {
# For reverse compatibility, add the brackets *after* the hook is
# run, and even add them to hook-provided text. (This is the main
# reason that the EditSectionLink hook is deprecated in favor of
# DoEditSectionLink: it can't change the brackets or the span.)
- $result = wfMsgHtml( 'editsection-brackets', $url );
+ $result = wfMsgHtml( 'editsection-brackets', $result );
return "<span class=\"editsection\">$result</span>";
}
# Add the brackets and the span, and *then* run the nice new hook, with
# clean and non-redundant arguments.
- $result = wfMsgHtml( 'editsection-brackets', $url );
+ $result = wfMsgHtml( 'editsection-brackets', $link );
$result = "<span class=\"editsection\">$result</span>";
wfRunHooks( 'DoEditSectionLink', array( $this, $nt, $section, $tooltip, &$result ) );
* @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>";
+ return "<a name=\"$anchor\" id=\"$anchor\"></a><h$level$attribs$link <span class=\"mw-headline\">$text</span></h$level>";
}
/**
}
$query['token'] = $wgUser->editToken( array( $title->getPrefixedText(),
$rev->getUserText() ) );
- return $this->link( $title, wfMsgHtml( 'rollbacklink' ), array(),
+ return $this->link( $title, wfMsgHtml( 'rollbacklink' ),
+ array( 'title' => wfMsg( 'tooltip-rollback' ) ),
$query, array( 'known', 'noclasses' ) );
}
* @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
} else {
$outText .= wfMsgExt( 'templatesused', array( 'parse' ) );
}
- $outText .= '</div><ul>';
+ $outText .= "</div><ul>\n";
usort( $templates, array( 'Title', 'compare' ) );
foreach ( $templates as $titleObj ) {
} 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>';
}
* 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>';
}
}
/**
- * 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) {
- $fname="Linker::tooltipAndAccesskey";
- wfProfileIn($fname);
- $out = '';
-
- $tooltip = wfMsg('tooltip-'.$name);
- if (!wfEmptyMsg('tooltip-'.$name, $tooltip) && $tooltip != '-') {
- // Compatibility: formerly some tooltips had [alt-.] hardcoded
- $tooltip = preg_replace( "/ ?\[alt-.\]$/", '', $tooltip );
- $out .= ' title="'.htmlspecialchars($tooltip);
+ public function tooltipAndAccesskey( $name ) {
+ # 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 ($out) $out .= " [$accesskey]\" accesskey=\"$accesskey\"";
- else $out .= " title=\"[$accesskey]\" accesskey=\"$accesskey\"";
- } elseif ($out) {
- $out .= '"';
+ if ( $attribs['accesskey'] === false ) {
+ unset( $attribs['accesskey'] );
}
- wfProfileOut($fname);
- return $out;
+ return Xml::expandAttributes( $attribs );
+ }
+
+ /** @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 )
+ ) );
}
/**
* 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 attribute, ready to drop in an element
- * (e.g., ' title="This does something"').
+ * @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 Contents of the title attribute (which you must HTML-
+ * escape), or false for no title attribute
+ */
+ public function titleAttrib( $name, $options = null ) {
+ wfProfileIn( __METHOD__ );
+
+ $tooltip = wfMsg( "tooltip-$name" );
+ # 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 ( $options == 'withaccess' ) {
+ $accesskey = $this->accesskey( $name );
+ if( $accesskey !== false ) {
+ if ( $tooltip === false || $tooltip === '' ) {
+ $tooltip = "[$accesskey]";
+ } else {
+ $tooltip .= " [$accesskey]";
+ }
+ }
+ }
+
+ wfProfileOut( __METHOD__ );
+ 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 tooltip($name) {
- $out = '';
+ public function accesskey( $name ) {
+ wfProfileIn( __METHOD__ );
+
+ $accesskey = wfMsg( "accesskey-$name" );
- $tooltip = wfMsg('tooltip-'.$name);
- if (!wfEmptyMsg('tooltip-'.$name, $tooltip) && $tooltip != '-') {
- $out = ' title="'.htmlspecialchars($tooltip).'"';
+ # 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;
}
- return $out;
+ wfProfileOut( __METHOD__ );
+ return false;
}
}