r99369 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r99368‎ | r99369 | r99370 >
Date:19:39, 9 October 2011
Author:dantman
Status:ok (Comments)
Tags:
Comment:
Fix up makeLinkItem and makeLink:
- Don't explicitly name attributes to use (fixes bug on language_links in 1.18)
- Allow makeLink to accept options specifying how to wrap links and text
Modified paths:
  • /trunk/phase3/includes/SkinTemplate.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/SkinTemplate.php
@@ -1643,43 +1643,73 @@
16441644 * If an "id" or "single-id" (if you don't want the actual id to be output on the link)
16451645 * is present it will be used to generate a tooltip and accesskey for the link.
16461646 * If you don't want an accesskey, set $item['tooltiponly'] = true;
 1647+ * $options can be used to affect the output of a link:
 1648+ * You can use a text-wrapper key to specify a list of elements to wrap the
 1649+ * text of a link in. This should be an array of arrays containing a 'tag' and
 1650+ * optionally an 'attributes' key. If you only have one element you don't need
 1651+ * to wrap it in another array. eg: To use <a><span>...</span></a> in all links
 1652+ * use array( 'text-wrapper' => array( 'tag' => 'span' ) ) for your options.
 1653+ * A link-class key can be used to specify additional classes to apply to all links.
 1654+ * A link-fallback can be used to specify a tag to use instead of <a> if there is
 1655+ * no link. eg: If you specify 'link-fallback' => 'span' than any non-link will
 1656+ * output a <span> instead of just text.
16471657 */
1648 - function makeLink( $key, $item ) {
 1658+ function makeLink( $key, $item, $options = array() ) {
16491659 if ( isset( $item['text'] ) ) {
16501660 $text = $item['text'];
16511661 } else {
16521662 $text = $this->translator->translate( isset( $item['msg'] ) ? $item['msg'] : $key );
16531663 }
16541664
1655 - if ( !isset( $item['href'] ) ) {
1656 - return htmlspecialchars( $text );
1657 - }
 1665+ $html = htmlspecialchars( $text );
16581666
1659 - $attrs = array();
1660 - foreach ( array( 'href', 'id', 'class', 'rel', 'type', 'target') as $attr ) {
1661 - if ( isset( $item[$attr] ) ) {
1662 - $attrs[$attr] = $item[$attr];
 1667+ if ( isset( $options['text-wrapper'] ) ) {
 1668+ $wrapper = $options['text-wrapper'];
 1669+ if ( isset( $wrapper['tag'] ) ) {
 1670+ $wrapper = array( $wrapper );
16631671 }
 1672+ while ( count( $wrapper ) > 0 ) {
 1673+ $element = array_pop( $wrapper );
 1674+ $html = Html::rawElement( $element['tag'], isset( $element['attributes'] ) ? $element['attributes'] : null, $html );
 1675+ }
16641676 }
16651677
1666 - if ( isset( $item['id'] ) ) {
1667 - $item['single-id'] = $item['id'];
1668 - }
1669 - if ( isset( $item['single-id'] ) ) {
1670 - if ( isset( $item['tooltiponly'] ) && $item['tooltiponly'] ) {
1671 - $attrs['title'] = Linker::titleAttrib( $item['single-id'] );
1672 - if ( $attrs['title'] === false ) {
1673 - unset( $attrs['title'] );
 1678+ if ( isset( $item['href'] ) || isset( $options['link-fallback'] ) ) {
 1679+ $attrs = $item;
 1680+ foreach ( array( 'single-id', 'text', 'msg', 'tooltiponly' ) as $k ) {
 1681+ unset( $attrs[$k] );
 1682+ }
 1683+
 1684+ if ( isset( $item['id'] ) && !isset( $item['single-id'] ) ) {
 1685+ $item['single-id'] = $item['id'];
 1686+ }
 1687+ if ( isset( $item['single-id'] ) ) {
 1688+ if ( isset( $item['tooltiponly'] ) && $item['tooltiponly'] ) {
 1689+ $title = Linker::titleAttrib( $item['single-id'] );
 1690+ if ( $title !== false ) {
 1691+ $attrs['title'] = $title;
 1692+ }
 1693+ } else {
 1694+ $tip = Linker::tooltipAndAccesskeyAttribs( $item['single-id'] );
 1695+ if ( isset( $tip['title'] ) && $tip['title'] !== false ) {
 1696+ $attrs['title'] = $tip['title'];
 1697+ }
 1698+ if ( isset( $tip['accesskey'] ) && $tip['accesskey'] !== false ) {
 1699+ $attrs['accesskey'] = $tip['accesskey'];
 1700+ }
16741701 }
1675 - } else {
1676 - $attrs = array_merge(
1677 - $attrs,
1678 - Linker::tooltipAndAccesskeyAttribs( $item['single-id'] )
1679 - );
16801702 }
 1703+ if ( isset( $options['link-class'] ) ) {
 1704+ if ( isset( $attrs['class'] ) ) {
 1705+ $attrs['class'] .= " {$options['link-class']}";
 1706+ } else {
 1707+ $attrs['class'] = $options['link-class'];
 1708+ }
 1709+ }
 1710+ $html = Html::rawElement( isset( $attrs['href'] ) ? 'a' : $options['link-fallback'], $attrs, $html );
16811711 }
16821712
1683 - return Html::element( 'a', $attrs, $text );
 1713+ return $html;
16841714 }
16851715
16861716 /**
@@ -1700,19 +1730,19 @@
17011731 * (however the link will still support a tooltip and accesskey from it)
17021732 * If you need an id or class on a single link you should include a "links"
17031733 * array with just one link item inside of it.
 1734+ * $options is also passed on to makeLink calls
17041735 */
17051736 function makeListItem( $key, $item, $options = array() ) {
17061737 if ( isset( $item['links'] ) ) {
17071738 $html = '';
17081739 foreach ( $item['links'] as $linkKey => $link ) {
1709 - $html .= $this->makeLink( $linkKey, $link );
 1740+ $html .= $this->makeLink( $linkKey, $link, $options );
17101741 }
17111742 } else {
1712 - $link = array();
1713 - foreach ( array( 'text', 'msg', 'href', 'rel', 'type', 'tooltiponly', 'target' ) as $k ) {
1714 - if ( isset( $item[$k] ) ) {
1715 - $link[$k] = $item[$k];
1716 - }
 1743+ $link = $item;
 1744+ // These keys are used by makeListItem and shouldn't be passed on to the link
 1745+ foreach ( array( 'id', 'class', 'active', 'tag' ) as $k ) {
 1746+ unset( $link[$k] );
17171747 }
17181748 if ( isset( $item['id'] ) ) {
17191749 // The id goes on the <li> not on the <a> for single links
@@ -1720,7 +1750,7 @@
17211751 // generating tooltips and accesskeys.
17221752 $link['single-id'] = $item['id'];
17231753 }
1724 - $html = $this->makeLink( $key, $link );
 1754+ $html = $this->makeLink( $key, $link, $options );
17251755 }
17261756
17271757 $attrs = array();

Follow-up revisions

RevisionCommit summaryAuthorDate
r102522REL1_18 MFT r99369reedy15:44, 9 November 2011

Comments

#Comment by Happy-melon (talk | contribs)   23:31, 27 October 2011

What's the usecase for the text-wrapper stuff? It looks like it'd most likely be more code than just using an Html::rawElement() directly, as well as being much less clear. It's far from obvious whether the text is escaped, for instance.

#Comment by Dantman (talk | contribs)   02:00, 28 October 2011

It's for designs that require things like every link inside of a list to have a <a>foo</a> so their site's css can actually make their design work.

#Comment by Hashar (talk | contribs)   22:32, 7 November 2011

removing this from 1.18. It is too late to have this new feature reviewed properly. Postponing to 1.19.

#Comment by Dantman (talk | contribs)   23:21, 7 November 2011

This was something for the BaseTemplate skin stuff I introduced in in 1.18.

The addition of link-fallback, link-class, and text-wrapper is somewhat minor and not used anywhere by default but it's something I really should have accounted for in the original BaseTemplate::makeLink code that I didn't at the time, and later realized when I attempted to use my own BaseTemplate code inside of a client project that needed it in order for the design to work. It's a minor feature but without it the BaseTemplate stuff isn't really complete.

Also in here is a fix for a regression caused by the BaseTemplate code. The language_urls had a title on them pre-1.18 but because I had this code white-listing attributes the title="" was being stripped out of stuff in the language box in skins updated to use makeListItem. On a suggestion from another user I switched the code to blacklist stuff actually used rather than only allow a limited subset of attributes.

#Comment by Krinkle (talk | contribs)   00:08, 20 December 2011

Should the Linker class support this (the 'text-wrapper' option for instance) independently from the Skin class, also ?

#Comment by Dantman (talk | contribs)   02:30, 20 December 2011

These options are for very skin-dependent markup design decisions (mostly hacks). For example making a list of links styled as a vertical menu of padding heavy buttons with a left area that acts as a coloured tab on the button by adding an extra span and applying some padding and two different background colours.

So no, I don't think the general linker should support this extra stuff. This is really here so that skins using the link builder for complex lists like we use in SkinTemplate don't have to resort to re-adding piles of complex markup to their skins just so that they can add an extra span inside every link in the list so their whole design will actually work.

Status & tagging log