diff options
Diffstat (limited to 'includes/Linker.php')
-rw-r--r-- | includes/Linker.php | 574 |
1 files changed, 371 insertions, 203 deletions
diff --git a/includes/Linker.php b/includes/Linker.php index b12e2ad0..9397b800 100644 --- a/includes/Linker.php +++ b/includes/Linker.php @@ -12,6 +12,12 @@ * @addtogroup Skins */ class Linker { + + /** + * Flags for userToolLinks() + */ + const TOOL_LINKS_NOBLOCK = 1; + function __construct() {} /** @@ -96,7 +102,7 @@ class Linker { wfProfileIn( 'Linker::makeLink' ); $nt = Title::newFromText( $title ); if ($nt) { - $result = $this->makeLinkObj( Title::newFromText( $title ), $text, $query, $trail ); + $result = $this->makeLinkObj( $nt, $text, $query, $trail ); } else { wfDebug( 'Invalid title passed to Linker::makeLink(): "'.$title."\"\n" ); $result = $text == "" ? $title : $text; @@ -218,32 +224,39 @@ class Linker { $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix ); } else { wfProfileIn( $fname.'-immediate' ); + + # Handles links to special pages wich do not exist in the database: + if( $nt->getNamespace() == NS_SPECIAL ) { + if( SpecialPage::exists( $nt->getDbKey() ) ) { + $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix ); + } else { + $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix ); + } + wfProfileOut( $fname.'-immediate' ); + wfProfileOut( $fname ); + return $retVal; + } + # Work out link colour immediately $aid = $nt->getArticleID() ; if ( 0 == $aid ) { $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix ); } else { - $threshold = $wgUser->getOption('stubthreshold') ; - if ( $threshold > 0 ) { - $dbr = wfGetDB( DB_SLAVE ); - $s = $dbr->selectRow( - array( 'page' ), - array( 'page_len', - 'page_namespace', - 'page_is_redirect' ), - array( 'page_id' => $aid ), $fname ) ; - if ( $s !== false ) { - $size = $s->page_len; - if ( $s->page_is_redirect OR $s->page_namespace != NS_MAIN ) { - $size = $threshold*2 ; # Really big - } - } else { - $size = $threshold*2 ; # Really big + $stub = false; + if ( $nt->isContentPage() ) { + $threshold = $wgUser->getOption('stubthreshold'); + if ( $threshold > 0 ) { + $dbr = wfGetDB( DB_SLAVE ); + $s = $dbr->selectRow( + array( 'page' ), + array( 'page_len', + 'page_is_redirect' ), + array( 'page_id' => $aid ), $fname ) ; + $stub = ( $s !== false && !$s->page_is_redirect && + $s->page_len < $threshold ); } - } else { - $size = 1 ; } - if ( $size < $threshold ) { + if ( $stub ) { $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix ); } else { $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix ); @@ -324,7 +337,9 @@ class Linker { $fname = 'Linker::makeBrokenLinkObj'; wfProfileIn( $fname ); - if ( '' == $query ) { + if( $nt->getNamespace() == NS_SPECIAL ) { + $q = $query; + } else if ( '' == $query ) { $q = 'action=edit'; } else { $q = 'action=edit&'.$query; @@ -418,42 +433,118 @@ class Linker { return $s; } - /** @todo document */ - function makeImageLinkObj( $nt, $label, $alt, $align = '', $params = array(), $framed = false, - $thumb = false, $manual_thumb = '', $valign = '' ) + /** + * Creates the HTML source for images + * @deprecated use makeImageLink2 + * + * @param object $title + * @param string $label label text + * @param string $alt alt text + * @param string $align horizontal alignment: none, left, center, right) + * @param array $handlerParams Parameters to be passed to the media handler + * @param boolean $framed shows image in original size in a frame + * @param boolean $thumb shows image as thumbnail in a frame + * @param string $manualthumb image name for the manual thumbnail + * @param string $valign vertical alignment: baseline, sub, super, top, text-top, middle, bottom, text-bottom + * @return string + */ + function makeImageLinkObj( $title, $label, $alt, $align = '', $handlerParams = array(), $framed = false, + $thumb = false, $manualthumb = '', $valign = '', $time = false ) { - global $wgContLang, $wgUser, $wgThumbLimits; - - $img = new Image( $nt ); + $frameParams = array( 'alt' => $alt, 'caption' => $label ); + if ( $align ) { + $frameParams['align'] = $align; + } + if ( $framed ) { + $frameParams['framed'] = true; + } + if ( $thumb ) { + $frameParams['thumbnail'] = true; + } + if ( $manualthumb ) { + $frameParams['manualthumb'] = $manualthumb; + } + if ( $valign ) { + $frameParams['valign'] = $valign; + } + $file = wfFindFile( $title, $time ); + return $this->makeImageLink2( $title, $file, $frameParams, $handlerParams ); + } - if ( !$img->allowInlineDisplay() && $img->exists() ) { - return $this->makeKnownLinkObj( $nt ); + /** + * Make an image link + * @param Title $title Title object + * @param File $file File object, or false if it doesn't exist + * + * @param array $frameParams Associative array of parameters external to the media handler. + * Boolean parameters are indicated by presence or absence, the value is arbitrary and + * will often be false. + * thumbnail If present, downscale and frame + * manualthumb Image name to use as a thumbnail, instead of automatic scaling + * framed Shows image in original size in a frame + * frameless Downscale but don't frame + * upright If present, tweak default sizes for portrait orientation + * upright_factor Fudge factor for "upright" tweak (default 0.75) + * border If present, show a border around the image + * align Horizontal alignment (left, right, center, none) + * valign Vertical alignment (baseline, sub, super, top, text-top, middle, + * bottom, text-bottom) + * alt Alternate text for image (i.e. alt attribute). Plain text. + * caption HTML for image caption. + * + * @param array $handlerParams Associative array of media handler parameters, to be passed + * to transform(). Typical keys are "width" and "page". + */ + function makeImageLink2( Title $title, $file, $frameParams = array(), $handlerParams = array() ) { + global $wgContLang, $wgUser, $wgThumbLimits, $wgThumbUpright; + if ( $file && !$file->allowInlineDisplay() ) { + wfDebug( __METHOD__.': '.$title->getPrefixedDBkey()." does not allow inline display\n" ); + return $this->makeKnownLinkObj( $title ); } - $error = $prefix = $postfix = ''; - $page = isset( $params['page'] ) ? $params['page'] : false; + // Shortcuts + $fp =& $frameParams; + $hp =& $handlerParams; - if ( 'center' == $align ) + // Clean up parameters + $page = isset( $hp['page'] ) ? $hp['page'] : false; + if ( !isset( $fp['align'] ) ) $fp['align'] = ''; + if ( !isset( $fp['alt'] ) ) $fp['alt'] = ''; + + $prefix = $postfix = ''; + + if ( 'center' == $fp['align'] ) { $prefix = '<div class="center">'; $postfix = '</div>'; - $align = 'none'; + $fp['align'] = 'none'; } + if ( $file && !isset( $hp['width'] ) ) { + $hp['width'] = $file->getWidth( $page ); - if ( !isset( $params['width'] ) ) { - $params['width'] = $img->getWidth( $page ); - if( $thumb || $framed ) { + if( isset( $fp['thumbnail'] ) || isset( $fp['framed'] ) || isset( $fp['frameless'] ) || !$hp['width'] ) { $wopt = $wgUser->getOption( 'thumbsize' ); if( !isset( $wgThumbLimits[$wopt] ) ) { $wopt = User::getDefaultOption( 'thumbsize' ); } - $params['width'] = min( $params['width'], $wgThumbLimits[$wopt] ); + // Reduce width for upright images when parameter 'upright' is used + if ( isset( $fp['upright'] ) && $fp['upright'] == 0 ) { + $fp['upright'] = $wgThumbUpright; + } + // Use width which is smaller: real image width or user preference width + // For caching health: If width scaled down due to upright parameter, round to full __0 pixel to avoid the creation of a lot of odd thumbs + $prefWidth = isset( $fp['upright'] ) ? + round( $wgThumbLimits[$wopt] * $fp['upright'], -1 ) : + $wgThumbLimits[$wopt]; + if ( $hp['width'] <= 0 || $prefWidth < $hp['width'] ) { + $hp['width'] = $prefWidth; + } } } - if ( $thumb || $framed ) { + 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- @@ -462,159 +553,174 @@ class Linker { # # If thumbnail width has not been provided, it is set # to the default user option as specified in Language*.php - if ( $align == '' ) { - $align = $wgContLang->isRTL() ? 'left' : 'right'; + if ( $fp['align'] == '' ) { + $fp['align'] = $wgContLang->isRTL() ? 'left' : 'right'; } - return $prefix.$this->makeThumbLinkObj( $img, $label, $alt, $align, $params, $framed, $manual_thumb ).$postfix; + return $prefix.$this->makeThumbLink2( $title, $file, $fp, $hp ).$postfix; } - if ( $params['width'] && $img->exists() ) { + if ( $file && $hp['width'] ) { # Create a resized image, without the additional thumbnail features - $thumb = $img->transform( $params ); + $thumb = $file->transform( $hp ); } else { $thumb = false; } - if ( $page ) { - $query = 'page=' . urlencode( $page ); - } else { - $query = ''; - } - $u = $nt->getLocalURL( $query ); - $imgAttribs = array( - 'alt' => $alt, - 'longdesc' => $u - ); - if ( $valign ) { - $imgAttribs['style'] = "vertical-align: $valign"; - } - $linkAttribs = array( - 'href' => $u, - 'class' => 'image', - 'title' => $alt - ); - if ( !$thumb ) { - $s = $this->makeBrokenImageLinkObj( $img->getTitle() ); + $s = $this->makeBrokenImageLinkObj( $title ); } else { - $s = $thumb->toHtml( $imgAttribs, $linkAttribs ); + $s = $thumb->toHtml( array( + 'desc-link' => true, + 'alt' => $fp['alt'], + 'valign' => isset( $fp['valign'] ) ? $fp['valign'] : false , + 'img-class' => isset( $fp['border'] ) ? 'thumbborder' : false ) ); } - if ( '' != $align ) { - $s = "<div class=\"float{$align}\"><span>{$s}</span></div>"; + if ( '' != $fp['align'] ) { + $s = "<div class=\"float{$fp['align']}\"><span>{$s}</span></div>"; } return str_replace("\n", ' ',$prefix.$s.$postfix); } /** * Make HTML for a thumbnail including image, border and caption - * $img is an Image object + * @param Title $title + * @param File $file File object or false if it doesn't exist */ - function makeThumbLinkObj( $img, $label = '', $alt, $align = 'right', $params = array(), $framed=false , $manual_thumb = "" ) { + function makeThumbLinkObj( Title $title, $file, $label = '', $alt, $align = 'right', $params = array(), $framed=false , $manualthumb = "" ) { + $frameParams = array( + 'alt' => $alt, + 'caption' => $label, + 'align' => $align + ); + if ( $framed ) $frameParams['framed'] = true; + if ( $manualthumb ) $frameParams['manualthumb'] = $manualthumb; + return $this->makeThumbLink2( $title, $file, $frameParams, $params ); + } + + function makeThumbLink2( Title $title, $file, $frameParams = array(), $handlerParams = array() ) { global $wgStylePath, $wgContLang; - $thumbUrl = ''; - $error = ''; + $exists = $file && $file->exists(); + + # Shortcuts + $fp =& $frameParams; + $hp =& $handlerParams; - $page = isset( $params['page'] ) ? $params['page'] : false; + $page = isset( $hp['page'] ) ? $hp['page'] : false; + if ( !isset( $fp['align'] ) ) $fp['align'] = 'right'; + if ( !isset( $fp['alt'] ) ) $fp['alt'] = ''; + if ( !isset( $fp['caption'] ) ) $fp['caption'] = ''; - if ( empty( $params['width'] ) ) { - $params['width'] = 180; + if ( empty( $hp['width'] ) ) { + // Reduce width for upright images when parameter 'upright' is used + $hp['width'] = isset( $fp['upright'] ) ? 130 : 180; } $thumb = false; - if ( $manual_thumb != '' ) { - # Use manually specified thumbnail - $manual_title = Title::makeTitleSafe( NS_IMAGE, $manual_thumb ); - if( $manual_title ) { - $manual_img = new Image( $manual_title ); - $thumb = $manual_img->getUnscaledThumb(); - } - } elseif ( $framed ) { - // Use image dimensions, don't scale - $thumb = $img->getUnscaledThumb( $page ); - } else { - $thumb = $img->transform( $params ); - } - if ( $thumb ) { - $outerWidth = $thumb->getWidth() + 2; + if ( !$exists ) { + $outerWidth = $hp['width'] + 2; } else { - $outerWidth = $params['width'] + 2; + if ( isset( $fp['manualthumb'] ) ) { + # Use manually specified thumbnail + $manual_title = Title::makeTitleSafe( NS_IMAGE, $fp['manualthumb'] ); + if( $manual_title ) { + $manual_img = wfFindFile( $manual_title ); + if ( $manual_img ) { + $thumb = $manual_img->getUnscaledThumb(); + } else { + $exists = false; + } + } + } elseif ( isset( $fp['framed'] ) ) { + // Use image dimensions, don't scale + $thumb = $file->getUnscaledThumb( $page ); + } else { + # Do not present an image bigger than the source, for bitmap-style images + # This is a hack to maintain compatibility with arbitrary pre-1.10 behaviour + $srcWidth = $file->getWidth( $page ); + if ( $srcWidth && !$file->mustRender() && $hp['width'] > $srcWidth ) { + $hp['width'] = $srcWidth; + } + $thumb = $file->transform( $hp ); + } + + if ( $thumb ) { + $outerWidth = $thumb->getWidth() + 2; + } else { + $outerWidth = $hp['width'] + 2; + } } $query = $page ? 'page=' . urlencode( $page ) : ''; - $u = $img->getTitle()->getLocalURL( $query ); + $url = $title->getLocalURL( $query ); $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) ); $magnifyalign = $wgContLang->isRTL() ? 'left' : 'right'; $textalign = $wgContLang->isRTL() ? ' style="text-align:right"' : ''; - $s = "<div class=\"thumb t{$align}\"><div class=\"thumbinner\" style=\"width:{$outerWidth}px;\">"; - if ( !$thumb ) { - $s .= htmlspecialchars( wfMsg( 'thumbnail_error', '' ) ); + $s = "<div class=\"thumb t{$fp['align']}\"><div class=\"thumbinner\" style=\"width:{$outerWidth}px;\">"; + if( !$exists ) { + $s .= $this->makeBrokenImageLinkObj( $title ); $zoomicon = ''; - } elseif( !$img->exists() ) { - $s .= $this->makeBrokenImageLinkObj( $img->getTitle() ); + } elseif ( !$thumb ) { + $s .= htmlspecialchars( wfMsg( 'thumbnail_error', '' ) ); $zoomicon = ''; } else { - $imgAttribs = array( - 'alt' => $alt, - 'longdesc' => $u, - 'class' => 'thumbimage' - ); - $linkAttribs = array( - 'href' => $u, - 'class' => 'internal', - 'title' => $alt - ); - - $s .= $thumb->toHtml( $imgAttribs, $linkAttribs ); - if ( $framed ) { + $s .= $thumb->toHtml( array( + 'alt' => $fp['alt'], + 'img-class' => 'thumbimage', + 'desc-link' => true ) ); + if ( isset( $fp['framed'] ) ) { $zoomicon=""; } else { $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'. - '<a href="'.$u.'" class="internal" title="'.$more.'">'. + '<a href="'.$url.'" class="internal" title="'.$more.'">'. '<img src="'.$wgStylePath.'/common/images/magnify-clip.png" ' . 'width="15" height="11" alt="" /></a></div>'; } } - $s .= ' <div class="thumbcaption"'.$textalign.'>'.$zoomicon.$label."</div></div></div>"; + $s .= ' <div class="thumbcaption"'.$textalign.'>'.$zoomicon.$fp['caption']."</div></div></div>"; return str_replace("\n", ' ', $s); } /** - * Pass a title object, not a title string + * Make a "broken" link to an image + * + * @param Title $title Image title + * @param string $text Link label + * @param string $query Query string + * @param string $trail Link trail + * @param string $prefix Link prefix + * @return string */ - function makeBrokenImageLinkObj( $nt, $text = '', $query = '', $trail = '', $prefix = '' ) { - # Fail gracefully - if ( ! isset($nt) ) { - # throw new MWException(); + public function makeBrokenImageLinkObj( $title, $text = '', $query = '', $trail = '', $prefix = '' ) { + global $wgEnableUploads; + if( $title instanceof Title ) { + wfProfileIn( __METHOD__ ); + if( $wgEnableUploads ) { + $upload = SpecialPage::getTitleFor( 'Upload' ); + if( $text == '' ) + $text = htmlspecialchars( $title->getPrefixedText() ); + $q = 'wpDestFile=' . $title->getPartialUrl(); + if( $query != '' ) + $q .= '&' . $query; + list( $inside, $trail ) = self::splitTrail( $trail ); + $style = $this->getInternalLinkAttributesObj( $title, $text, 'yes' ); + wfProfileOut( __METHOD__ ); + return '<a href="' . $upload->escapeLocalUrl( $q ) . '"' + . $style . '>' . $prefix . $text . $inside . '</a>' . $trail; + } else { + wfProfileOut( __METHOD__ ); + return $this->makeKnownLinkObj( $title, $text, $query, $trail, $prefix ); + } + } else { return "<!-- ERROR -->{$prefix}{$text}{$trail}"; } - - $fname = 'Linker::makeBrokenImageLinkObj'; - wfProfileIn( $fname ); - - $q = 'wpDestFile=' . urlencode( $nt->getDBkey() ); - if ( '' != $query ) { - $q .= "&$query"; - } - $uploadTitle = SpecialPage::getTitleFor( 'Upload' ); - $url = $uploadTitle->escapeLocalURL( $q ); - - if ( '' == $text ) { - $text = htmlspecialchars( $nt->getPrefixedText() ); - } - $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" ); - list( $inside, $trail ) = Linker::splitTrail( $trail ); - $s = "<a href=\"{$url}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}"; - - wfProfileOut( $fname ); - return $s; } - /** @todo document */ - function makeMediaLink( $name, /* wtf?! */ $url, $alt = '' ) { + /** @deprecated use Linker::makeMediaLinkObj() */ + function makeMediaLink( $name, $unused = '', $text = '' ) { $nt = Title::makeTitleSafe( NS_IMAGE, $name ); - return $this->makeMediaLinkObj( $nt, $alt ); + return $this->makeMediaLinkObj( $nt, $text ); } /** @@ -632,13 +738,13 @@ class Linker { ### HOTFIX. Instead of breaking, return empty string. return $text; } else { - $img = new Image( $title ); - if( $img->exists() ) { + $img = wfFindFile( $title ); + if( $img ) { $url = $img->getURL(); $class = 'internal'; } else { $upload = SpecialPage::getTitleFor( 'Upload' ); - $url = $upload->getLocalUrl( 'wpDestFile=' . urlencode( $img->getName() ) ); + $url = $upload->getLocalUrl( 'wpDestFile=' . urlencode( $title->getDbKey() ) ); $class = 'new'; } $alt = htmlspecialchars( $title->getText() ); @@ -694,15 +800,18 @@ class Linker { } /** - * @param $userId Integer: user id in database. - * @param $userText String: user name in database. - * @param $redContribsWhenNoEdits Bool: return a red contribs link when the user had no edits and this is true. - * @return string HTML fragment with talk and/or block links + * Generate standard user tool links (talk, contributions, block link, etc.) + * + * @param int $userId User identifier + * @param string $userText User name or IP address + * @param bool $redContribsWhenNoEdits Should the contributions link be red if the user has no edits? + * @param int $flags Customisation flags (e.g. self::TOOL_LINKS_NOBLOCK) + * @return string */ - public function userToolLinks( $userId, $userText, $redContribsWhenNoEdits = false ) { + public function userToolLinks( $userId, $userText, $redContribsWhenNoEdits = false, $flags = 0 ) { global $wgUser, $wgDisableAnonTalk, $wgSysopUserBans; $talkable = !( $wgDisableAnonTalk && 0 == $userId ); - $blockable = ( $wgSysopUserBans || 0 == $userId ); + $blockable = ( $wgSysopUserBans || 0 == $userId ) && !$flags & self::TOOL_LINKS_NOBLOCK; $items = array(); if( $talkable ) { @@ -711,7 +820,7 @@ class Linker { if( $userId ) { // check if the user has an edit if( $redContribsWhenNoEdits && User::edits( $userId ) == 0 ) { - $style = "class='new'"; + $style = " class='new'"; } else { $style = ''; } @@ -818,16 +927,33 @@ class Linker { function formatComment($comment, $title = NULL, $local = false) { wfProfileIn( __METHOD__ ); - global $wgContLang; + # Sanitize text a bit: $comment = str_replace( "\n", " ", $comment ); $comment = htmlspecialchars( $comment ); - # The pattern for autogen comments is / * foo * /, which makes for - # some nasty regex. - # We look for all comments, match any text before and after the comment, - # add a separator where needed and format the comment itself with CSS + # Render autocomments and make links: + $comment = $this->formatAutoComments( $comment, $title, $local ); + $comment = $this->formatLinksInComment( $comment ); + + wfProfileOut( __METHOD__ ); + return $comment; + } + + /** + * The pattern for autogen comments is / * foo * /, which makes for + * some nasty regex. + * We look for all comments, match any text before and after the comment, + * add a separator where needed and format the comment itself with CSS + * Called by Linker::formatComment. + * + * @param $comment Comment text + * @param $title An optional title object used to links to sections + * + * @todo Document the $local parameter. + */ + private function formatAutocomments( $comment, $title = NULL, $local = false ) { $match = array(); - while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) { + while (preg_match('!(.*)/\*\s*(.*?)\s*\*/(.*)!', $comment,$match)) { $pre=$match[1]; $auto=$match[2]; $post=$match[3]; @@ -859,10 +985,23 @@ class Linker { $comment=$pre.$auto.$post; } - # format regular and media links - all other wiki formatting - # is ignored + return $comment; + } + + /** + * Formats wiki links and media links in text; all other wiki formatting + * is ignored + * + * @param string $comment Text to format links in + * @return string + */ + public function formatLinksInComment( $comment ) { + global $wgContLang; + $medians = '(?:' . preg_quote( Namespace::getCanonicalName( NS_MEDIA ), '/' ) . '|'; $medians .= preg_quote( $wgContLang->getNsText( NS_MEDIA ), '/' ) . '):'; + + $match = array(); while(preg_match('/\[\[:?(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) { # Handle link renaming [[foo|text]] will show link as "text" if( "" != $match[3] ) { @@ -889,7 +1028,7 @@ class Linker { } $comment = preg_replace( $linkRegexp, StringUtils::escapeRegexReplacement( $thelink ), $comment, 1 ); } - wfProfileOut( __METHOD__ ); + return $comment; } @@ -914,7 +1053,7 @@ class Linker { return " <span class=\"comment\">($formatted)</span>"; } } - + /** * Wrap and format the given revision's comment block, if the current * user is allowed to view it. @@ -981,31 +1120,66 @@ class Linker { . "</script>\n"; } - /** @todo document */ + /** + * Used to generate section edit links that point to "other" pages + * (sections that are really part of included pages). + * + * @param $title Title string. + * @param $section Integer: section number. + */ public function editSectionLinkForOther( $title, $section ) { - global $wgContLang; - $title = Title::newFromText( $title ); - $editurl = '§ion='.$section; - $url = $this->makeKnownLinkObj( $title, wfMsg('editsection'), 'action=edit'.$editurl ); - - return "<span class=\"editsection\">[".$url."]</span>"; - + return $this->doEditSectionLink( $title, $section, '', 'EditSectionLinkForOther' ); } /** - * @param $title Title object. + * @param $nt Title object. * @param $section Integer: section number. * @param $hint Link String: title, or default if omitted or empty */ - public function editSectionLink( $nt, $section, $hint='' ) { - global $wgContLang; + public function editSectionLink( Title $nt, $section, $hint='' ) { + if( $hint != '' ) { + $hint = wfMsgHtml( 'editsectionhint', htmlspecialchars( $hint ) ); + $hint = " title=\"$hint\""; + } + return $this->doEditSectionLink( $nt, $section, $hint, 'EditSectionLink' ); + } + /** + * Implement editSectionLink and editSectionLinkForOther. + * + * @param $nt Title object + * @param $section Integer, section number + * @param $hint String, for HTML title attribute + * @param $hook String, name of hook to run + * @return String, HTML to use for edit link + */ + protected function doEditSectionLink( Title $nt, $section, $hint, $hook ) { + global $wgContLang; $editurl = '§ion='.$section; - $hint = ( $hint=='' ) ? '' : ' title="' . wfMsgHtml( 'editsectionhint', htmlspecialchars( $hint ) ) . '"'; - $url = $this->makeKnownLinkObj( $nt, wfMsg('editsection'), 'action=edit'.$editurl, '', '', '', $hint ); + $url = $this->makeKnownLinkObj( + $nt, + wfMsg('editsection'), + 'action=edit'.$editurl, + '', '', '', $hint + ); + $result = null; - return "<span class=\"editsection\">[".$url."]</span>"; + // The two hooks have slightly different interfaces . . . + if( $hook == 'EditSectionLink' ) { + wfRunHooks( $hook, array( &$this, $nt, $section, $hint, $url, &$result ) ); + } elseif( $hook == 'EditSectionLinkForOther' ) { + wfRunHooks( $hook, array( &$this, $nt, $section, $url, &$result ) ); + } + + // For reverse compatibility, add the brackets *after* the hook is run, + // and even add them to hook-provided text. + if( is_null( $result ) ) { + $result = wfMsg( 'editsection-brackets', $url ); + } else { + $result = wfMsg( 'editsection-brackets', $result ); + } + return "<span class=\"editsection\">$result</span>"; } /** @@ -1061,15 +1235,28 @@ class Linker { * @param Revision $rev */ function generateRollback( $rev ) { - global $wgUser, $wgRequest; + return '<span class="mw-rollback-link">[' + . $this->buildRollbackLink( $rev ) + . ']</span>'; + } + + /** + * Build a raw rollback link, useful for collections of "tool" links + * + * @param Revision $rev + * @return string + */ + public function buildRollbackLink( $rev ) { + global $wgRequest, $wgUser; $title = $rev->getTitle(); - - $extraRollback = $wgRequest->getBool( 'bot' ) ? '&bot=1' : ''; - $extraRollback .= '&token=' . urlencode( - $wgUser->editToken( array( $title->getPrefixedText(), $rev->getUserText() ) ) ); - return '<span class="mw-rollback-link">['. $this->makeKnownLinkObj( $title, - wfMsg('rollbacklink'), - 'action=rollback&from=' . urlencode( $rev->getUserText() ) . $extraRollback ) .']</span>'; + $extra = $wgRequest->getBool( 'bot' ) ? '&bot=1' : ''; + $extra .= '&token=' . urlencode( $wgUser->editToken( array( $title->getPrefixedText(), + $rev->getUserText() ) ) ); + return $this->makeKnownLinkObj( + $title, + wfMsgHtml( 'rollbacklink' ), + 'action=rollback&from=' . urlencode( $rev->getUserText() ) . $extra + ); } /** @@ -1133,28 +1320,7 @@ class Linker { */ public function formatSize( $size ) { global $wgLang; - // For small sizes no decimal places necessary - $round = 0; - if( $size > 1024 ) { - $size = $size / 1024; - if( $size > 1024 ) { - $size = $size / 1024; - // For MB and bigger two decimal places are smarter - $round = 2; - if( $size > 1024 ) { - $size = $size / 1024; - $msg = 'size-gigabytes'; - } else { - $msg = 'size-megabytes'; - } - } else { - $msg = 'size-kilobytes'; - } - } else { - $msg = 'size-bytes'; - } - $size = round( $size, $round ); - return wfMsgHtml( $msg, $wgLang->formatNum( $size ) ); + return htmlspecialchars( $wgLang->formatSize( $size ) ); } /** @@ -1208,4 +1374,6 @@ class Linker { } } -?> + + + |