function toHTML() { global $wgLang; $sk = $this->getSkin(); $params = array('width' => $this->mWidths, 'height' => $this->mHeights); $i = 0; $images = array(); foreach ($this->mImages as $pair) { $nt = $pair[0]; $text = $pair[1]; # Give extensions a chance to select the file revision for us $time = $descQuery = false; $img = wfFindFile($nt, $time); if ($nt->getNamespace() != NS_FILE || !$img) { # We're dealing with a non-image, spit out the name and be done with it. } elseif ($this->mHideBadImages && wfIsBadImage($nt->getDBkey(), $this->getContextTitle())) { # The image is blacklisted, just show it as a text link. } elseif ($this->mWidths && $this->mHeights && !($thumb = $img->transform($params))) { # Error generating thumbnail. } elseif ($img->getMediaType() != 'BITMAP' && $img->getMediaType() != 'DRAWING' && $img->getMediaType() != 'MEDIATYPE_BITMAP' && $img->getMediaType() != 'MEDIATYPE_DRAWING') { # non image, ignore } else { array_push($images, $pair); } } if (count($images) > 0) { $this->mImages = $images; $html = ImageGalleryOriginal::toHTML(); // remove links $trace = debug_backtrace(); $caller = $trace[1]; if ($caller['class'] == 'ParserOriginal' || $caller['class'] == 'Parser') { preg_match_all('/<a [^>]*>(.*?<img.*?)<\\/a>/s', $html, $matches); if (count($matches)) { $html = str_replace($matches[0], $matches[1], $html); } } return $html; } return ""; }
/** * Return a HTML representation of the image gallery * * For each image in the gallery, display * - a thumbnail * - the image name * - the additional text provided when adding the image * - the size of the image * * @return string */ function toHTML() { if ($this->mPerRow > 0) { $maxwidth = $this->mPerRow * ($this->mWidths + $this->getAllPadding()); $oldStyle = isset($this->mAttribs['style']) ? $this->mAttribs['style'] : ''; # _width is ignored by any sane browser. IE6 doesn't know max-width # so it uses _width instead $this->mAttribs['style'] = "max-width: {$maxwidth}px;_width: {$maxwidth}px;" . $oldStyle; } $attribs = Sanitizer::mergeAttributes(['class' => 'gallery mw-gallery-' . $this->mMode], $this->mAttribs); $modules = $this->getModules(); if ($this->mParser) { $this->mParser->getOutput()->addModules($modules); $this->mParser->getOutput()->addModuleStyles('mediawiki.page.gallery.styles'); } else { $this->getOutput()->addModules($modules); $this->getOutput()->addModuleStyles('mediawiki.page.gallery.styles'); } $output = Xml::openElement('ul', $attribs); if ($this->mCaption) { $output .= "\n\t<li class='gallerycaption'>{$this->mCaption}</li>"; } if ($this->mShowFilename) { // Preload LinkCache info for when generating links // of the filename below $lb = new LinkBatch(); foreach ($this->mImages as $img) { $lb->addObj($img[0]); } $lb->execute(); } $lang = $this->getRenderLang(); # Output each image... foreach ($this->mImages as $pair) { /** @var Title $nt */ $nt = $pair[0]; $text = $pair[1]; # "text" means "caption" here $alt = $pair[2]; $link = $pair[3]; $descQuery = false; if ($nt->getNamespace() === NS_FILE) { # Get the file... if ($this->mParser instanceof Parser) { # Give extensions a chance to select the file revision for us $options = []; Hooks::run('BeforeParserFetchFileAndTitle', [$this->mParser, $nt, &$options, &$descQuery]); # Fetch and register the file (file title may be different via hooks) list($img, $nt) = $this->mParser->fetchFileAndTitle($nt, $options); } else { $img = wfFindFile($nt); } } else { $img = false; } $params = $this->getThumbParams($img); // $pair[4] is per image handler options $transformOptions = $params + $pair[4]; $thumb = false; if (!$img) { # We're dealing with a non-image, spit out the name and be done with it. $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' . ($this->getThumbPadding() + $this->mHeights) . 'px;">' . htmlspecialchars($nt->getText()) . '</div>'; if ($this->mParser instanceof Parser) { $this->mParser->addTrackingCategory('broken-file-category'); } } elseif ($this->mHideBadImages && wfIsBadImage($nt->getDBkey(), $this->getContextTitle())) { # The image is blacklisted, just show it as a text link. $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' . ($this->getThumbPadding() + $this->mHeights) . 'px;">' . Linker::linkKnown($nt, htmlspecialchars($nt->getText())) . '</div>'; } else { $thumb = $img->transform($transformOptions); if (!$thumb) { # Error generating thumbnail. $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' . ($this->getThumbPadding() + $this->mHeights) . 'px;">' . htmlspecialchars($img->getLastError()) . '</div>'; } else { /** @var MediaTransformOutput $thumb */ $vpad = $this->getVPad($this->mHeights, $thumb->getHeight()); $imageParameters = ['desc-link' => true, 'desc-query' => $descQuery, 'alt' => $alt, 'custom-url-link' => $link]; // In the absence of both alt text and caption, fall back on // providing screen readers with the filename as alt text if ($alt == '' && $text == '') { $imageParameters['alt'] = $nt->getText(); } $this->adjustImageParameters($thumb, $imageParameters); Linker::processResponsiveImages($img, $thumb, $transformOptions); # Set both fixed width and min-height. $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="width: ' . $this->getThumbDivWidth($thumb->getWidth()) . 'px;">' . '<div style="margin:' . $vpad . 'px auto;">' . $thumb->toHtml($imageParameters) . '</div></div>'; // Call parser transform hook /** @var MediaHandler $handler */ $handler = $img->getHandler(); if ($this->mParser && $handler) { $handler->parserTransformHook($this->mParser, $img); } } } // @todo Code is incomplete. // $linkTarget = Title::newFromText( $wgContLang->getNsText( MWNamespace::getUser() ) . // ":{$ut}" ); // $ul = Linker::link( $linkTarget, $ut ); if ($this->mShowBytes) { if ($img) { $fileSize = htmlspecialchars($lang->formatSize($img->getSize())); } else { $fileSize = $this->msg('filemissing')->escaped(); } $fileSize = "{$fileSize}<br />\n"; } else { $fileSize = ''; } $textlink = $this->mShowFilename ? Linker::linkKnown($nt, htmlspecialchars($lang->truncate($nt->getText(), $this->mCaptionLength))) . "<br />\n" : ''; $galleryText = $textlink . $text . $fileSize; $galleryText = $this->wrapGalleryText($galleryText, $thumb); # Weird double wrapping (the extra div inside the li) needed due to FF2 bug # Can be safely removed if FF2 falls completely out of existence $output .= "\n\t\t" . '<li class="gallerybox" style="width: ' . $this->getGBWidth($thumb) . 'px">' . '<div style="width: ' . $this->getGBWidth($thumb) . 'px">' . $thumbhtml . $galleryText . "\n\t\t</div></li>"; } $output .= "\n</ul>"; return $output; }
/** * Return a HTML representation of the image gallery * * For each image in the gallery, display * - a thumbnail * - the image name * - the additional text provided when adding the image * - the size of the image * */ function toHTML() { global $wgLang; $sk = $this->getSkin(); $attribs = Sanitizer::mergeAttributes(array('class' => 'gallery', 'cellspacing' => '0', 'cellpadding' => '0'), $this->mAttribs); $s = Xml::openElement('table', $attribs); if ($this->mCaption) { $s .= "\n\t<caption>{$this->mCaption}</caption>"; } $params = array('width' => $this->mWidths, 'height' => $this->mHeights); $i = 0; foreach ($this->mImages as $pair) { $nt = $pair[0]; $text = $pair[1]; # Give extensions a chance to select the file revision for us $time = $descQuery = false; wfRunHooks('BeforeGalleryFindFile', array(&$this, &$nt, &$time, &$descQuery)); $img = wfFindFile($nt, $time); if ($nt->getNamespace() != NS_FILE || !$img) { # We're dealing with a non-image, spit out the name and be done with it. $thumbhtml = "\n\t\t\t" . '<div style="height: ' . ($this->mHeights * 1.25 + 2) . 'px;">' . htmlspecialchars($nt->getText()) . '</div>'; } elseif ($this->mHideBadImages && wfIsBadImage($nt->getDBkey(), $this->getContextTitle())) { # The image is blacklisted, just show it as a text link. $thumbhtml = "\n\t\t\t" . '<div style="height: ' . ($this->mHeights * 1.25 + 2) . 'px;">' . $sk->makeKnownLinkObj($nt, htmlspecialchars($nt->getText())) . '</div>'; } elseif (!($thumb = $img->transform($params))) { # Error generating thumbnail. $thumbhtml = "\n\t\t\t" . '<div style="height: ' . ($this->mHeights * 1.25 + 2) . 'px;">' . htmlspecialchars($img->getLastError()) . '</div>'; } else { $vpad = floor((1.25 * $this->mHeights - $thumb->height) / 2) - 2; $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="padding: ' . $vpad . 'px 0; width: ' . ($this->mWidths + 30) . 'px;">' . '<div style="margin-left: auto; margin-right: auto; width: ' . $this->mWidths . 'px;">' . $thumb->toHtml(array('desc-link' => true, 'desc-query' => $descQuery)) . '</div></div>'; // Call parser transform hook if ($this->mParser && $img->getHandler()) { $img->getHandler()->parserTransformHook($this->mParser, $img); } } //TODO //$ul = $sk->makeLink( $wgContLang->getNsText( MWNamespace::getUser() ) . ":{$ut}", $ut ); if ($this->mShowBytes) { if ($img) { $nb = wfMsgExt('nbytes', array('parsemag', 'escape'), $wgLang->formatNum($img->getSize())); } else { $nb = wfMsgHtml('filemissing'); } $nb = "{$nb}<br />\n"; } else { $nb = ''; } $textlink = $this->mShowFilename ? $sk->makeKnownLinkObj($nt, htmlspecialchars($wgLang->truncate($nt->getText(), 20, '...'))) . "<br />\n" : ''; # ATTENTION: The newline after <div class="gallerytext"> is needed to accommodate htmltidy which # in version 4.8.6 generated crackpot html in its absence, see: # http://bugzilla.wikimedia.org/show_bug.cgi?id=1765 -Ævar if ($i % $this->mPerRow == 0) { $s .= "\n\t<tr>"; } $s .= "\n\t\t" . '<td><div class="gallerybox" style="width: ' . ($this->mWidths + 35) . 'px;">' . $thumbhtml . "\n\t\t\t" . '<div class="gallerytext">' . "\n" . $textlink . $text . $nb . "\n\t\t\t</div>" . "\n\t\t</div></td>"; if ($i % $this->mPerRow == $this->mPerRow - 1) { $s .= "\n\t</tr>"; } ++$i; } if ($i % $this->mPerRow != 0) { $s .= "\n\t</tr>"; } $s .= "\n</table>"; return $s; }
/** * Process [[ ]] wikilinks (RIL) * @param $s * @throws MWException * @return LinkHolderArray * * @private */ function replaceInternalLinks2(&$s) { wfProfileIn(__METHOD__); wfProfileIn(__METHOD__ . '-setup'); static $tc = false, $e1, $e1_img; # the % is needed to support urlencoded titles as well if (!$tc) { $tc = Title::legalChars() . '#%'; # Match a link having the form [[namespace:link|alternate]]trail $e1 = "/^([{$tc}]+)(?:\\|(.+?))?]](.*)\$/sD"; # Match cases where there is no "]]", which might still be images $e1_img = "/^([{$tc}]+)\\|(.*)\$/sD"; } $holders = new LinkHolderArray($this); # split the entire text string on occurrences of [[ $a = StringUtils::explode('[[', ' ' . $s); # get the first element (all text up to first [[), and remove the space we added $s = $a->current(); $a->next(); $line = $a->current(); # Workaround for broken ArrayIterator::next() that returns "void" $s = substr($s, 1); $useLinkPrefixExtension = $this->getTargetLanguage()->linkPrefixExtension(); $e2 = null; if ($useLinkPrefixExtension) { # Match the end of a line for a word that's not followed by whitespace, # e.g. in the case of 'The Arab al[[Razi]]', 'al' will be matched global $wgContLang; $charset = $wgContLang->linkPrefixCharset(); $e2 = "/^((?>.*[^{$charset}]|))(.+)\$/sDu"; } if (is_null($this->mTitle)) { wfProfileOut(__METHOD__ . '-setup'); wfProfileOut(__METHOD__); throw new MWException(__METHOD__ . ": \$this->mTitle is null\n"); } $nottalk = !$this->mTitle->isTalkPage(); if ($useLinkPrefixExtension) { $m = array(); if (preg_match($e2, $s, $m)) { $first_prefix = $m[2]; } else { $first_prefix = false; } } else { $prefix = ''; } $useSubpages = $this->areSubpagesAllowed(); wfProfileOut(__METHOD__ . '-setup'); # Loop for each link for (; $line !== false && $line !== null; $a->next(), $line = $a->current()) { # Check for excessive memory usage if ($holders->isBig()) { # Too big # Do the existence check, replace the link holders and clear the array $holders->replace($s); $holders->clear(); } if ($useLinkPrefixExtension) { wfProfileIn(__METHOD__ . '-prefixhandling'); if (preg_match($e2, $s, $m)) { $prefix = $m[2]; $s = $m[1]; } else { $prefix = ''; } # first link if ($first_prefix) { $prefix = $first_prefix; $first_prefix = false; } wfProfileOut(__METHOD__ . '-prefixhandling'); } $might_be_img = false; wfProfileIn(__METHOD__ . "-e1"); if (preg_match($e1, $line, $m)) { # page with normal text or alt $text = $m[2]; # If we get a ] at the beginning of $m[3] that means we have a link that's something like: # [[Image:Foo.jpg|[http://example.com desc]]] <- having three ] in a row f***s up, # the real problem is with the $e1 regex # See bug 1300. # # Still some problems for cases where the ] is meant to be outside punctuation, # and no image is in sight. See bug 2095. # if ($text !== '' && substr($m[3], 0, 1) === ']' && strpos($text, '[') !== false) { $text .= ']'; # so that replaceExternalLinks($text) works later $m[3] = substr($m[3], 1); } # fix up urlencoded title texts if (strpos($m[1], '%') !== false) { # Should anchors '#' also be rejected? $m[1] = str_replace(array('<', '>'), array('<', '>'), rawurldecode($m[1])); } $trail = $m[3]; } elseif (preg_match($e1_img, $line, $m)) { # Invalid, but might be an image with a link in its caption $might_be_img = true; $text = $m[2]; if (strpos($m[1], '%') !== false) { $m[1] = rawurldecode($m[1]); } $trail = ""; } else { # Invalid form; output directly $s .= $prefix . '[[' . $line; wfProfileOut(__METHOD__ . "-e1"); continue; } wfProfileOut(__METHOD__ . "-e1"); wfProfileIn(__METHOD__ . "-misc"); # Don't allow internal links to pages containing # PROTO: where PROTO is a valid URL protocol; these # should be external links. if (preg_match('/^(?i:' . $this->mUrlProtocols . ')/', $m[1])) { $s .= $prefix . '[[' . $line; wfProfileOut(__METHOD__ . "-misc"); continue; } # Make subpage if necessary if ($useSubpages) { $link = $this->maybeDoSubpageLink($m[1], $text); } else { $link = $m[1]; } $noforce = substr($m[1], 0, 1) !== ':'; if (!$noforce) { # Strip off leading ':' $link = substr($link, 1); } wfProfileOut(__METHOD__ . "-misc"); wfProfileIn(__METHOD__ . "-title"); $nt = Title::newFromText($this->mStripState->unstripNoWiki($link)); if ($nt === null) { $s .= $prefix . '[[' . $line; wfProfileOut(__METHOD__ . "-title"); continue; } $ns = $nt->getNamespace(); $iw = $nt->getInterwiki(); wfProfileOut(__METHOD__ . "-title"); if ($might_be_img) { # if this is actually an invalid link wfProfileIn(__METHOD__ . "-might_be_img"); if ($ns == NS_FILE && $noforce) { # but might be an image $found = false; while (true) { # look at the next 'line' to see if we can close it there $a->next(); $next_line = $a->current(); if ($next_line === false || $next_line === null) { break; } $m = explode(']]', $next_line, 3); if (count($m) == 3) { # the first ]] closes the inner link, the second the image $found = true; $text .= "[[{$m[0]}]]{$m[1]}"; $trail = $m[2]; break; } elseif (count($m) == 2) { # if there's exactly one ]] that's fine, we'll keep looking $text .= "[[{$m[0]}]]{$m[1]}"; } else { # if $next_line is invalid too, we need look no further $text .= '[[' . $next_line; break; } } if (!$found) { # we couldn't find the end of this imageLink, so output it raw # but don't ignore what might be perfectly normal links in the text we've examined $holders->merge($this->replaceInternalLinks2($text)); $s .= "{$prefix}[[{$link}|{$text}"; # note: no $trail, because without an end, there *is* no trail wfProfileOut(__METHOD__ . "-might_be_img"); continue; } } else { # it's not an image, so output it raw $s .= "{$prefix}[[{$link}|{$text}"; # note: no $trail, because without an end, there *is* no trail wfProfileOut(__METHOD__ . "-might_be_img"); continue; } wfProfileOut(__METHOD__ . "-might_be_img"); } $wasblank = $text == ''; if ($wasblank) { $text = $link; } else { # Bug 4598 madness. Handle the quotes only if they come from the alternate part # [[Lista d''e paise d''o munno]] -> <a href="...">Lista d''e paise d''o munno</a> # [[Criticism of Harry Potter|Criticism of ''Harry Potter'']] # -> <a href="Criticism of Harry Potter">Criticism of <i>Harry Potter</i></a> $text = $this->doQuotes($text); } # Link not escaped by : , create the various objects if ($noforce) { # Interwikis wfProfileIn(__METHOD__ . "-interwiki"); if ($iw && $this->mOptions->getInterwikiMagic() && $nottalk && Language::fetchLanguageName($iw, null, 'mw')) { // XXX: the above check prevents links to sites with identifiers that are not language codes # Bug 24502: filter duplicates if (!isset($this->mLangLinkLanguages[$iw])) { $this->mLangLinkLanguages[$iw] = true; $this->mOutput->addLanguageLink($nt->getFullText()); } $s = rtrim($s . $prefix); $s .= trim($trail, "\n") == '' ? '' : $prefix . $trail; wfProfileOut(__METHOD__ . "-interwiki"); continue; } wfProfileOut(__METHOD__ . "-interwiki"); if ($ns == NS_FILE) { wfProfileIn(__METHOD__ . "-image"); if (!wfIsBadImage($nt->getDBkey(), $this->mTitle)) { if ($wasblank) { # if no parameters were passed, $text # becomes something like "File:Foo.png", # which we don't want to pass on to the # image generator $text = ''; } else { # recursively parse links inside the image caption # actually, this will parse them in any other parameters, too, # but it might be hard to fix that, and it doesn't matter ATM $text = $this->replaceExternalLinks($text); $holders->merge($this->replaceInternalLinks2($text)); } # cloak any absolute URLs inside the image markup, so replaceExternalLinks() won't touch them $s .= $prefix . $this->armorLinks($this->makeImage($nt, $text, $holders)) . $trail; } else { $s .= $prefix . $trail; } wfProfileOut(__METHOD__ . "-image"); continue; } if ($ns == NS_CATEGORY) { wfProfileIn(__METHOD__ . "-category"); $s = rtrim($s . "\n"); # bug 87 if ($wasblank) { $sortkey = $this->getDefaultSort(); } else { $sortkey = $text; } $sortkey = Sanitizer::decodeCharReferences($sortkey); $sortkey = str_replace("\n", '', $sortkey); $sortkey = $this->getConverterLanguage()->convertCategoryKey($sortkey); $this->mOutput->addCategory($nt->getDBkey(), $sortkey); /** * Strip the whitespace Category links produce, see bug 87 */ $s .= trim($prefix . $trail, "\n") == '' ? '' : $prefix . $trail; wfProfileOut(__METHOD__ . "-category"); continue; } } # Self-link checking. For some languages, variants of the title are checked in # LinkHolderArray::doVariants() to allow batching the existence checks necessary # for linking to a different variant. if ($ns != NS_SPECIAL && $nt->equals($this->mTitle) && !$nt->hasFragment()) { $s .= $prefix . Linker::makeSelfLinkObj($nt, $text, '', $trail); continue; } # NS_MEDIA is a pseudo-namespace for linking directly to a file # @todo FIXME: Should do batch file existence checks, see comment below if ($ns == NS_MEDIA) { wfProfileIn(__METHOD__ . "-media"); # Give extensions a chance to select the file revision for us $options = array(); $descQuery = false; wfRunHooks('BeforeParserFetchFileAndTitle', array($this, $nt, &$options, &$descQuery)); # Fetch and register the file (file title may be different via hooks) list($file, $nt) = $this->fetchFileAndTitle($nt, $options); # Cloak with NOPARSE to avoid replacement in replaceExternalLinks $s .= $prefix . $this->armorLinks(Linker::makeMediaLinkFile($nt, $file, $text)) . $trail; wfProfileOut(__METHOD__ . "-media"); continue; } wfProfileIn(__METHOD__ . "-always_known"); # Some titles, such as valid special pages or files in foreign repos, should # be shown as bluelinks even though they're not included in the page table # # @todo FIXME: isAlwaysKnown() can be expensive for file links; we should really do # batch file existence checks for NS_FILE and NS_MEDIA if ($iw == '' && $nt->isAlwaysKnown()) { $this->mOutput->addLink($nt); $s .= $this->makeKnownLinkHolder($nt, $text, array(), $trail, $prefix); } else { # Links will be added to the output link list after checking $s .= $holders->makeHolder($nt, $text, array(), $trail, $prefix); } wfProfileOut(__METHOD__ . "-always_known"); } wfProfileOut(__METHOD__); return $holders; }
function toHTML() { global $wgLang, $mvDefaultAspectRatio; $sk = $this->getSkin(); $attribs = Sanitizer::mergeAttributes(array('class' => 'gallery', 'cellspacing' => '0', 'cellpadding' => '0'), $this->mAttribs); $s = Xml::openElement('table', $attribs); if ($this->mCaption) { $s .= "\n\t<caption>" . htmlspecialchars($this->mCaption) . "</caption>"; } $params = array('width' => $this->mWidths, 'height' => $this->mHeights); $i = 0; $this->already_named_resource = array(); foreach ($this->mImages as $pair) { $nt = $pair[0]; $text = $pair[1]; # Give extensions a chance to select the file revision for us $time = false; wfRunHooks('BeforeGalleryFindFile', array(&$this, &$nt, &$time)); $img = wfFindFile($nt, array('time' => $time)); if ($nt->getNamespace() == MV_NS_MVD || $nt->getNamespace() == MV_NS_STREAM || $nt->getNamespace() == MV_NS_SEQUENCE) { // @@todo fix sequence embed // $vpad = floor( ( 1.25*$this->mHeights - $thumb->height ) /2 ) - 2; $mvTitle = new MV_Title($nt); // remap MVD namespace links into the Stream view (so contextual metadata is present) if ($nt->getNamespace() == MV_NS_MVD) { $nt = Title::MakeTitle(MV_NS_STREAM, ucfirst($mvTitle->getStreamName()) . '/' . $mvTitle->getTimeRequest()); } $vidH = round($this->mWidths * $mvDefaultAspectRatio); $vidRes = $this->mWidths . 'x' . $vidH; // print "img url: " . $mvTitle->getStreamImageURL(); $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="padding: 4px 0; width: ' . htmlspecialchars($this->mWidths + 5) . 'px;">' . '<div style="margin-left: auto; margin-right: auto; width: ' . htmlspecialchars($this->mWidths) . 'px;">' . $sk->makeKnownLinkObj($nt, '<img title="' . htmlspecialchars($mvTitle->getStreamNameText()) . '"' . ' width="160" height="120" src="' . $mvTitle->getStreamImageURL('160x120') . '">') . '</div>' . '</div>' . '<span class="gallerytext" style="float:left">' . $sk->makeKnownLinkObj($nt, $mvTitle->getStreamNameText() . ' ' . $mvTitle->getTimeDesc()) . '</span>' . '</div>'; $nb = ''; $textlink = ''; } else { if ($nt->getNamespace() != NS_IMAGE || !$img) { # We're dealing with a non-image, spit out the name and be done with it. $thumbhtml = "\n\t\t\t" . '<div style="height: ' . ($this->mHeights * 1.25 + 2) . 'px;">' . htmlspecialchars($nt->getText()) . '</div>'; } elseif ($this->mHideBadImages && wfIsBadImage($nt->getDBkey(), $this->getContextTitle())) { # The image is blacklisted, just show it as a text link. $thumbhtml = "\n\t\t\t" . '<div style="height: ' . ($this->mHeights * 1.25 + 2) . 'px;">' . $sk->makeKnownLinkObj($nt, htmlspecialchars($nt->getText())) . '</div>'; } elseif (!($thumb = $img->transform($params))) { # Error generating thumbnail. $thumbhtml = "\n\t\t\t" . '<div style="height: ' . ($this->mHeights * 1.25 + 2) . 'px;">' . htmlspecialchars($img->getLastError()) . '</div>'; } else { $vpad = floor((1.25 * $this->mHeights - $thumb->height) / 2) - 2; $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="padding: ' . htmlspecialchars($vpad) . 'px 0; width: ' . htmlspecialchars($this->mWidths + 30) . 'px;">' . '<div style="margin-left: auto; margin-right: auto; width: ' . htmlspecialchars($this->mWidths) . 'px;">' . $thumb->toHtml(array('desc-link' => true)) . '</div></div>'; // Call parser transform hook if ($this->mParser && $img->getHandler()) { $img->getHandler()->parserTransformHook($this->mParser, $img); } } if ($this->mShowBytes) { if ($img) { $nb = wfMsgExt('nbytes', array('parsemag', 'escape'), $wgLang->formatNum($img->getSize())); } else { $nb = wfMsgHtml('filemissing'); } $nb = "{$nb}<br />\n"; } else { $nb = ''; } $textlink = $this->mShowFilename ? $sk->makeKnownLinkObj($nt, htmlspecialchars($wgLang->truncate($nt->getText(), 20))) . "<br />\n" : ''; } # ATTENTION: The newline after <div class="gallerytext"> is needed to accommodate htmltidy which # in version 4.8.6 generated crackpot html in its absence, see: # http://bugzilla.wikimedia.org/show_bug.cgi?id=1765 -Ævar if ($i % $this->mPerRow == 0) { $s .= "\n\t<tr>"; } $s .= "\n\t\t" . '<td><div class="gallerybox" style="width: ' . ($this->mWidths + 10) . 'px;">' . $thumbhtml . "\n\t\t\t" . '<div class="gallerytext">' . "\n" . $textlink . htmlspecialchars($text) . $nb . "\n\t\t\t</div>" . "\n\t\t</div></td>"; if ($i % $this->mPerRow == $this->mPerRow - 1) { $s .= "\n\t</tr>"; } ++$i; } if ($i % $this->mPerRow != 0) { $s .= "\n\t</tr>"; } $s .= "\n</table>"; return $s; }
/** * Return a HTML representation of the image gallery * * For each image in the gallery, display * - a thumbnail * - the image name * - the additional text provided when adding the image * - the size of the image * */ function toHTML() { global $wgLang, $wgIgnoreImageErrors, $wgGenerateThumbnailOnParse; $sk = $this->getSkin(); $s = '<table class="gallery" cellspacing="0" cellpadding="0">'; if ($this->mCaption) { $s .= '<td class="galleryheader" colspan="4"><big>' . htmlspecialchars($this->mCaption) . '</big></td>'; } $i = 0; foreach ($this->mImages as $pair) { $img =& $pair[0]; $text = $pair[1]; $name = $img->getName(); $nt = $img->getTitle(); if ($nt->getNamespace() != NS_IMAGE) { # We're dealing with a non-image, spit out the name and be done with it. $thumbhtml = '<div style="height: 152px;">' . htmlspecialchars($nt->getText()) . '</div>'; } else { if ($this->mParsing && wfIsBadImage($nt->getDBkey())) { # The image is blacklisted, just show it as a text link. $thumbhtml = '<div style="height: 152px;">' . $sk->makeKnownLinkObj($nt, htmlspecialchars($nt->getText())) . '</div>'; } else { if (!($thumb = $img->getThumbnail(120, 120, $wgGenerateThumbnailOnParse))) { # Error generating thumbnail. $thumbhtml = '<div style="height: 152px;">' . htmlspecialchars($img->getLastError()) . '</div>'; } else { $vpad = floor((150 - $thumb->height) / 2) - 2; $thumbhtml = '<div class="thumb" style="padding: ' . $vpad . 'px 0;">' . $sk->makeKnownLinkObj($nt, $thumb->toHtml()) . '</div>'; } } } //TODO //$ul = $sk->makeLink( $wgContLang->getNsText( Namespace::getUser() ) . ":{$ut}", $ut ); if ($this->mShowBytes) { if ($img->exists()) { $nb = wfMsgExt('nbytes', array('parsemag', 'escape'), $wgLang->formatNum($img->getSize())); } else { $nb = wfMsgHtml('filemissing'); } $nb = "{$nb}<br />\n"; } else { $nb = ''; } $textlink = $this->mShowFilename ? $sk->makeKnownLinkObj($nt, htmlspecialchars($wgLang->truncate($nt->getText(), 20, '...'))) . "<br />\n" : ''; # ATTENTION: The newline after <div class="gallerytext"> is needed to accommodate htmltidy which # in version 4.8.6 generated crackpot html in its absence, see: # http://bugzilla.wikimedia.org/show_bug.cgi?id=1765 -Ævar $s .= $i % 4 == 0 ? '<tr>' : ''; $s .= '<td><div class="gallerybox">' . $thumbhtml . '<div class="gallerytext">' . "\n" . $textlink . $text . $nb . "</div></div></td>\n"; $s .= $i % 4 == 3 ? '</tr>' : ''; $i++; } if ($i % 4 != 0) { $s .= "</tr>\n"; } $s .= '</table>'; return $s; }
static function render($input, $params, $parser) { global $wgScriptPath, $wgUser, $wgUrlProtocols, $wgNoFollowLinks; wfLoadExtensionMessages('ImageMap'); $lines = explode("\n", $input); $first = true; $lineNum = 0; $mapHTML = ''; $links = array(); # Define canonical desc types to allow i18n of 'imagemap_desc_types' $descTypesCanonical = 'top-right, bottom-right, bottom-left, top-left, none'; $descType = self::BOTTOM_RIGHT; $defaultLinkAttribs = false; $realmap = true; foreach ($lines as $line) { ++$lineNum; $externLink = false; $line = trim($line); if ($line == '' || $line[0] == '#') { continue; } if ($first) { $first = false; # The first line should have an image specification on it # Extract it and render the HTML $bits = explode('|', $line, 2); if (count($bits) == 1) { $image = $bits[0]; $options = ''; } else { list($image, $options) = $bits; } $imageTitle = Title::newFromText($image); if (!$imageTitle || $imageTitle->getNamespace() != NS_IMAGE) { return self::error('imagemap_no_image'); } if (wfIsBadImage($imageTitle->getDBkey(), $parser->mTitle)) { return self::error('imagemap_bad_image'); } // Parse the options so we can use links and the like in the caption $parsedOptions = $parser->recursiveTagParse($options); $imageHTML = $parser->makeImage($imageTitle, $parsedOptions); $parser->replaceLinkHolders($imageHTML); $imageHTML = $parser->mStripState->unstripBoth($imageHTML); $imageHTML = Sanitizer::normalizeCharReferences($imageHTML); $parser->mOutput->addImage($imageTitle->getDBkey()); $domDoc = new DOMDocument(); wfSuppressWarnings(); $ok = $domDoc->loadXML($imageHTML); wfRestoreWarnings(); if (!$ok) { return self::error('imagemap_invalid_image'); } $xpath = new DOMXPath($domDoc); $imgs = $xpath->query('//img'); if (!$imgs->length) { return self::error('imagemap_invalid_image'); } $imageNode = $imgs->item(0); $thumbWidth = $imageNode->getAttribute('width'); $thumbHeight = $imageNode->getAttribute('height'); if (function_exists('wfFindFile')) { $imageObj = wfFindFile($imageTitle); } else { // Old MW $imageObj = wfFindFile($imageTitle); } if (!$imageObj || !$imageObj->exists()) { return self::error('imagemap_invalid_image'); } # Add the linear dimensions to avoid inaccuracy in the scale # factor when one is much larger than the other # (sx+sy)/(x+y) = s $denominator = $imageObj->getWidth() + $imageObj->getHeight(); $numerator = $thumbWidth + $thumbHeight; if ($denominator <= 0 || $numerator <= 0) { return self::error('imagemap_invalid_image'); } $scale = $numerator / $denominator; continue; } # Handle desc spec $cmd = strtok($line, " \t"); if ($cmd == 'desc') { $typesText = wfMsgForContent('imagemap_desc_types'); if ($descTypesCanonical != $typesText) { // i18n desc types exists $typesText = $descTypesCanonical . ', ' . $typesText; } $types = array_map('trim', explode(',', $typesText)); $type = trim(strtok('')); $descType = array_search($type, $types); if ($descType > 4) { // A localized descType is used. Subtract 5 to reach the canonical desc type. $descType = $descType - 5; } if ($descType === false || $descType < 0) { // <0? In theory never, but paranoia... return self::error('imagemap_invalid_desc', $typesText); } continue; } # Find the link $link = trim(strstr($line, '[')); if (preg_match('/^ \\[\\[ ([^|]*+) \\| ([^\\]]*+) \\]\\] \\w* $ /x', $link, $m)) { $title = Title::newFromText($m[1]); $alt = trim($m[2]); } elseif (preg_match('/^ \\[\\[ ([^\\]]*+) \\]\\] \\w* $ /x', $link, $m)) { $title = Title::newFromText($m[1]); if (is_null($title)) { return self::error('imagemap_invalid_title', $lineNum); } $alt = $title->getFullText(); } elseif (in_array(substr($link, 1, strpos($link, '//') + 1), $wgUrlProtocols) || in_array(substr($link, 1, strpos($link, ':')), $wgUrlProtocols)) { if (preg_match('/^ \\[ ([^\\s]*+) \\s ([^\\]]*+) \\] \\w* $ /x', $link, $m)) { $title = $m[1]; $alt = trim($m[2]); $externLink = true; } elseif (preg_match('/^ \\[ ([^\\]]*+) \\] \\w* $ /x', $link, $m)) { $title = $alt = trim($m[1]); $externLink = true; } } else { return self::error('imagemap_no_link', $lineNum); } if (!$title) { return self::error('imagemap_invalid_title', $lineNum); } $shapeSpec = substr($line, 0, -strlen($link)); # Tokenize shape spec $shape = strtok($shapeSpec, " \t"); switch ($shape) { case 'default': $coords = array(); break; case 'rect': $coords = self::tokenizeCoords(4, $lineNum); if (!is_array($coords)) { return $coords; } break; case 'circle': $coords = self::tokenizeCoords(3, $lineNum); if (!is_array($coords)) { return $coords; } break; case 'poly': $coords = array(); $coord = strtok(" \t"); while ($coord !== false) { $coords[] = $coord; $coord = strtok(" \t"); } if (!count($coords)) { return self::error('imagemap_missing_coord', $lineNum); } if (count($coords) % 2 !== 0) { return self::error('imagemap_poly_odd', $lineNum); } break; default: return self::error('imagemap_unrecognised_shape', $lineNum); } # Scale the coords using the size of the source image foreach ($coords as $i => $c) { $coords[$i] = intval(round($c * $scale)); } # Construct the area tag $attribs = array(); if ($externLink) { $attribs['href'] = $title; $attribs['class'] = 'plainlinks'; if ($wgNoFollowLinks) { $attribs['rel'] = 'nofollow'; } } else { if ($title->getFragment() != '' && $title->getPrefixedDBkey() == '') { # XXX: kluge to handle [[#Fragment]] links, should really fix getLocalURL() # in Title.php to return an empty string in this case $attribs['href'] = $title->getFragmentForURL(); } else { $attribs['href'] = $title->escapeLocalURL() . $title->getFragmentForURL(); } } if ($shape != 'default') { $attribs['shape'] = $shape; } if ($coords) { $attribs['coords'] = implode(',', $coords); } if ($alt != '') { if ($shape != 'default') { $attribs['alt'] = $alt; } $attribs['title'] = $alt; } if ($shape == 'default') { $defaultLinkAttribs = $attribs; } else { $mapHTML .= Xml::element('area', $attribs) . "\n"; } if ($externLink) { $extLinks[] = $title; } else { $links[] = $title; } } if ($first) { return self::error('imagemap_no_image'); } if ($mapHTML == '' && $defaultLinkAttribs == '') { return self::error('imagemap_no_areas'); } elseif ($mapHTML == '' && $defaultLinkAttribs != '') { // no areas defined, default only. It's not a real imagemap, so we do not need some tags $realmap = false; } if ($realmap) { # Construct the map # Add random number to avoid breaking cached HTML fragments that are # later joined together on the one page (bug 16471) $mapName = "ImageMap_" . ++self::$id . '_' . mt_rand(0, 0x7fffffff); $mapHTML = "<map name=\"{$mapName}\">\n{$mapHTML}</map>\n"; # Alter the image tag $imageNode->setAttribute('usemap', "#{$mapName}"); } # Add a surrounding div, remove the default link to the description page $anchor = $imageNode->parentNode; $parent = $anchor->parentNode; $div = $parent->insertBefore(new DOMElement('div'), $anchor); if ($defaultLinkAttribs) { $defaultAnchor = $div->appendChild(new DOMElement('a')); foreach ($defaultLinkAttribs as $name => $value) { $defaultAnchor->setAttribute($name, $value); } $imageParent = $defaultAnchor; } else { $imageParent = $div; } # Add the map HTML to the div # We used to add it before the div, but that made tidy unhappy if ($mapHTML != '') { $mapDoc = new DOMDocument(); $mapDoc->loadXML($mapHTML); $mapNode = $domDoc->importNode($mapDoc->documentElement, true); $div->appendChild($mapNode); } $imageParent->appendChild($imageNode->cloneNode(true)); $parent->removeChild($anchor); # Determine whether a "magnify" link is present $xpath = new DOMXPath($domDoc); $magnify = $xpath->query('//div[@class="magnify"]'); if (!$magnify->length && $descType != self::NONE) { # Add image description link if ($descType == self::TOP_LEFT || $descType == self::BOTTOM_LEFT) { $marginLeft = 0; } else { $marginLeft = $thumbWidth - 20; } if ($descType == self::TOP_LEFT || $descType == self::TOP_RIGHT) { $marginTop = -$thumbHeight; // 1px hack for IE, to stop it poking out the top $marginTop += 1; } else { $marginTop = -20; } $div->setAttribute('style', "height: {$thumbHeight}px; width: {$thumbWidth}px; "); $descWrapper = $div->appendChild(new DOMElement('div')); $descWrapper->setAttribute('style', "margin-left: {$marginLeft}px; " . "margin-top: {$marginTop}px; " . "text-align: left;"); $descAnchor = $descWrapper->appendChild(new DOMElement('a')); $descAnchor->setAttribute('href', $imageTitle->escapeLocalURL()); $descAnchor->setAttribute('title', wfMsgForContent('imagemap_description')); $descImg = $descAnchor->appendChild(new DOMElement('img')); $descImg->setAttribute('alt', wfMsgForContent('imagemap_description')); $descImg->setAttribute('src', "{$wgScriptPath}/extensions/ImageMap/desc-20.png"); $descImg->setAttribute('style', 'border: none;'); } # Output the result # We use saveXML() not saveHTML() because then we get XHTML-compliant output. # The disadvantage is that we have to strip out the DTD $output = preg_replace('/<\\?xml[^?]*\\?>/', '', $domDoc->saveXML()); # Register links foreach ($links as $title) { if ($title->isExternal() || $title->getNamespace() == NS_SPECIAL) { // Don't register special or interwiki links... } elseif ($title->getNamespace() == NS_MEDIA) { // Regular Media: links are recorded as image usages $parser->mOutput->addImage($title->getDBkey()); } else { // Plain ol' link $parser->mOutput->addLink($title); } } if (isset($extLinks)) { foreach ($extLinks as $title) { $parser->mOutput->addExternalLink($title); } } # Armour output against broken parser $output = str_replace("\n", '', $output); return $output; }
/** * Process [[ ]] wikilinks * * @private */ function replaceInternalLinks($s) { global $wgContLang; static $fname = 'Parser::replaceInternalLinks'; wfProfileIn($fname); wfProfileIn($fname . '-setup'); static $tc = FALSE; # the % is needed to support urlencoded titles as well if (!$tc) { $tc = Title::legalChars() . '#%'; } $sk = $this->mOptions->getSkin(); #split the entire text string on occurences of [[ $a = explode('[[', ' ' . $s); #get the first element (all text up to first [[), and remove the space we added $s = array_shift($a); $s = substr($s, 1); # Match a link having the form [[namespace:link|alternate]]trail static $e1 = FALSE; if (!$e1) { $e1 = "/^([{$tc}]+)(?:\\|(.+?))?]](.*)\$/sD"; } # Match cases where there is no "]]", which might still be images static $e1_img = FALSE; if (!$e1_img) { $e1_img = "/^([{$tc}]+)\\|(.*)\$/sD"; } $useLinkPrefixExtension = $wgContLang->linkPrefixExtension(); $e2 = null; if ($useLinkPrefixExtension) { # Match the end of a line for a word that's not followed by whitespace, # e.g. in the case of 'The Arab al[[Razi]]', 'al' will be matched $e2 = wfMsgForContent('linkprefix'); } if (is_null($this->mTitle)) { throw new MWException(__METHOD__ . ": \$this->mTitle is null\n"); } $nottalk = !$this->mTitle->isTalkPage(); if ($useLinkPrefixExtension) { $m = array(); if (preg_match($e2, $s, $m)) { $first_prefix = $m[2]; } else { $first_prefix = false; } } else { $prefix = ''; } if ($wgContLang->hasVariants()) { $selflink = $wgContLang->convertLinkToAllVariants($this->mTitle->getPrefixedText()); } else { $selflink = array($this->mTitle->getPrefixedText()); } $useSubpages = $this->areSubpagesAllowed(); wfProfileOut($fname . '-setup'); # Loop for each link for ($k = 0; isset($a[$k]); $k++) { $line = $a[$k]; if ($useLinkPrefixExtension) { wfProfileIn($fname . '-prefixhandling'); if (preg_match($e2, $s, $m)) { $prefix = $m[2]; $s = $m[1]; } else { $prefix = ''; } # first link if ($first_prefix) { $prefix = $first_prefix; $first_prefix = false; } wfProfileOut($fname . '-prefixhandling'); } $might_be_img = false; wfProfileIn("{$fname}-e1"); if (preg_match($e1, $line, $m)) { # page with normal text or alt $text = $m[2]; # If we get a ] at the beginning of $m[3] that means we have a link that's something like: # [[Image:Foo.jpg|[http://example.com desc]]] <- having three ] in a row f***s up, # the real problem is with the $e1 regex # See bug 1300. # # Still some problems for cases where the ] is meant to be outside punctuation, # and no image is in sight. See bug 2095. # if ($text !== '' && substr($m[3], 0, 1) === ']' && strpos($text, '[') !== false) { $text .= ']'; # so that replaceExternalLinks($text) works later $m[3] = substr($m[3], 1); } # fix up urlencoded title texts if (strpos($m[1], '%') !== false) { # Should anchors '#' also be rejected? $m[1] = str_replace(array('<', '>'), array('<', '>'), urldecode($m[1])); } $trail = $m[3]; } elseif (preg_match($e1_img, $line, $m)) { # Invalid, but might be an image with a link in its caption $might_be_img = true; $text = $m[2]; if (strpos($m[1], '%') !== false) { $m[1] = urldecode($m[1]); } $trail = ""; } else { # Invalid form; output directly $s .= $prefix . '[[' . $line; wfProfileOut("{$fname}-e1"); continue; } wfProfileOut("{$fname}-e1"); wfProfileIn("{$fname}-misc"); # Don't allow internal links to pages containing # PROTO: where PROTO is a valid URL protocol; these # should be external links. if (preg_match('/^\\b(?:' . wfUrlProtocols() . ')/', $m[1])) { $s .= $prefix . '[[' . $line; continue; } # Make subpage if necessary if ($useSubpages) { $link = $this->maybeDoSubpageLink($m[1], $text); } else { $link = $m[1]; } $noforce = substr($m[1], 0, 1) != ':'; if (!$noforce) { # Strip off leading ':' $link = substr($link, 1); } wfProfileOut("{$fname}-misc"); wfProfileIn("{$fname}-title"); $nt = Title::newFromText($this->mStripState->unstripNoWiki($link)); if (!$nt) { $s .= $prefix . '[[' . $line; wfProfileOut("{$fname}-title"); continue; } $ns = $nt->getNamespace(); $iw = $nt->getInterWiki(); wfProfileOut("{$fname}-title"); if ($might_be_img) { # if this is actually an invalid link wfProfileIn("{$fname}-might_be_img"); if ($ns == NS_IMAGE && $noforce) { #but might be an image $found = false; while (isset($a[$k + 1])) { #look at the next 'line' to see if we can close it there $spliced = array_splice($a, $k + 1, 1); $next_line = array_shift($spliced); $m = explode(']]', $next_line, 3); if (count($m) == 3) { # the first ]] closes the inner link, the second the image $found = true; $text .= "[[{$m[0]}]]{$m[1]}"; $trail = $m[2]; break; } elseif (count($m) == 2) { #if there's exactly one ]] that's fine, we'll keep looking $text .= "[[{$m[0]}]]{$m[1]}"; } else { #if $next_line is invalid too, we need look no further $text .= '[[' . $next_line; break; } } if (!$found) { # we couldn't find the end of this imageLink, so output it raw #but don't ignore what might be perfectly normal links in the text we've examined $text = $this->replaceInternalLinks($text); $s .= "{$prefix}[[{$link}|{$text}"; # note: no $trail, because without an end, there *is* no trail wfProfileOut("{$fname}-might_be_img"); continue; } } else { #it's not an image, so output it raw $s .= "{$prefix}[[{$link}|{$text}"; # note: no $trail, because without an end, there *is* no trail wfProfileOut("{$fname}-might_be_img"); continue; } wfProfileOut("{$fname}-might_be_img"); } $wasblank = '' == $text; if ($wasblank) { $text = $link; } # Link not escaped by : , create the various objects if ($noforce) { # Interwikis wfProfileIn("{$fname}-interwiki"); if ($iw && $this->mOptions->getInterwikiMagic() && $nottalk && $wgContLang->getLanguageName($iw)) { $this->mOutput->addLanguageLink($nt->getFullText()); $s = rtrim($s . $prefix); $s .= trim($trail, "\n") == '' ? '' : $prefix . $trail; wfProfileOut("{$fname}-interwiki"); continue; } wfProfileOut("{$fname}-interwiki"); if ($ns == NS_IMAGE) { wfProfileIn("{$fname}-image"); if (!wfIsBadImage($nt->getDBkey(), $this->mTitle)) { # recursively parse links inside the image caption # actually, this will parse them in any other parameters, too, # but it might be hard to fix that, and it doesn't matter ATM $text = $this->replaceExternalLinks($text); $text = $this->replaceInternalLinks($text); # cloak any absolute URLs inside the image markup, so replaceExternalLinks() won't touch them $s .= $prefix . $this->armorLinks($this->makeImage($nt, $text)) . $trail; $this->mOutput->addImage($nt->getDBkey()); wfProfileOut("{$fname}-image"); continue; } else { # We still need to record the image's presence on the page $this->mOutput->addImage($nt->getDBkey()); } wfProfileOut("{$fname}-image"); } if ($ns == NS_CATEGORY) { wfProfileIn("{$fname}-category"); $s = rtrim($s . "\n"); # bug 87 if ($wasblank) { $sortkey = $this->getDefaultSort(); } else { $sortkey = $text; } $sortkey = Sanitizer::decodeCharReferences($sortkey); $sortkey = str_replace("\n", '', $sortkey); $sortkey = $wgContLang->convertCategoryKey($sortkey); $this->mOutput->addCategory($nt->getDBkey(), $sortkey); /** * Strip the whitespace Category links produce, see bug 87 * @todo We might want to use trim($tmp, "\n") here. */ $s .= trim($prefix . $trail, "\n") == '' ? '' : $prefix . $trail; wfProfileOut("{$fname}-category"); continue; } } # Self-link checking if ($nt->getFragment() === '') { if (in_array($nt->getPrefixedText(), $selflink, true)) { $s .= $prefix . $sk->makeSelfLinkObj($nt, $text, '', $trail); continue; } } # Special and Media are pseudo-namespaces; no pages actually exist in them if ($ns == NS_MEDIA) { $link = $sk->makeMediaLinkObj($nt, $text); # Cloak with NOPARSE to avoid replacement in replaceExternalLinks $s .= $prefix . $this->armorLinks($link) . $trail; $this->mOutput->addImage($nt->getDBkey()); continue; } elseif ($ns == NS_SPECIAL) { if (SpecialPage::exists($nt->getDBkey())) { $s .= $this->makeKnownLinkHolder($nt, $text, '', $trail, $prefix); } else { $s .= $this->makeLinkHolder($nt, $text, '', $trail, $prefix); } continue; } elseif ($ns == NS_IMAGE) { $img = wfFindFile($nt); if ($img) { // Force a blue link if the file exists; may be a remote // upload on the shared repository, and we want to see its // auto-generated page. $s .= $this->makeKnownLinkHolder($nt, $text, '', $trail, $prefix); $this->mOutput->addLink($nt); continue; } } $s .= $this->makeLinkHolder($nt, $text, '', $trail, $prefix); } wfProfileOut($fname); return $s; }
/** * * @param File $img * @param Title $nt * @param string $text * @param string $alt * @param type $descQuery * @return string */ private function thumbToHTML($img, $nt, $text = '', $alt = '', $descQuery = '') { if (!$img) { $html = '<a class="CarError" style="height: ' . $this->mThumbHeight . 'px; width: ' . $this->mThumbWidth . 'px;">' . htmlspecialchars($nt->getText()) . '</a>'; } else { if ($this->mHideBadImages && wfIsBadImage($nt->getDBkey(), $this->getContextTitle())) { $html = '<a class="CarError" style="height: ' . $this->mThumbHeight . 'px; width: ' . $this->mThumbWidth . 'px;">' . Linker::link($nt, htmlspecialchars($nt->getText()), array(), array(), array('known', 'noclasses')) . '</a>'; } else { if (self::imgIsVertical($img)) { $params = array('height' => $this->mPhotoHeight, 'width' => $this->mThumbHeight); } else { $params = array('height' => $this->mThumbHeight, 'width' => $this->mPhotoWidth); } if (!($thumb = $img->transform($params))) { # Error generating thumbnail. $html = '<a class="CarError" style="height: ' . $this->mThumbHeight . 'px; width: ' . $this->mThumbWidth . 'px;"></a>'; } else { $imageParameters = array('desc-link' => true, 'desc-query' => $descQuery, 'alt' => $alt); # In the absence of both alt text and caption, fall back on providing screen readers with the filename as alt text if ($alt == '') { $imageParameters['alt'] = $nt->getText(); } $html = $thumb->toHtml($imageParameters); } } } return $html; }
/** * Return a HTML representation of the image slideshow */ private function renderSlideshow() { global $wgStylePath; wfProfileIn(__METHOD__); // don't render empty slideshows if (empty($this->mFiles)) { wfProfileOut(__METHOD__); return ''; } // If we can, render this as a media gallery if ($this->canRenderMediaGallery()) { $html = $this->renderMediaGallery(); wfProfileOut(__METHOD__); return trim(preg_replace('/\\n+/', ' ', $html)); } /** @var Skin|Linker $sk The Skin object falls back to Linker methods */ $sk = RequestContext::getMain()->getSkin(); // slideshow wrapper CSS class $class = 'wikia-slideshow clearfix'; $id = "slideshow-{$this->mData['id']}"; // do not add button for galleries from templates if (isset($this->mData['params']['source']) && $this->mData['params']['source'] == "template") { $class .= ' template'; } // support "position" attribute (slideshow alignment) switch ($this->getParam('position')) { case 'left': $class .= ' floatleft'; break; case 'center': $class .= ' slideshow-center'; break; case 'right': $class .= ' floatright'; break; } // wrap image slideshow inside div.slideshow $attribs = Sanitizer::mergeAttributes(array('class' => $class, 'data-hash' => $this->mData['hash'], 'data-crop' => $this->mCrop, 'id' => $id), $this->mAttribs); //renderSlideshow for WikiaMobile if (F::app()->checkSkin('wikiamobile')) { $slideshowHtml = $this->renderWikiaMobileMediaGroup(); } else { $slideshowHtml = Xml::openElement('div', $attribs); // render slideshow caption if ($this->mCaption) { $slideshowHtml .= '<div class="wikia-slideshow-caption">' . $this->mCaption . '</div>'; } // fit images inside width:height = 4:3 box $this->mHeights = round($this->mWidths * 3 / 4); $params = array('width' => $this->mWidths, 'height' => $this->mHeights); wfDebug(__METHOD__ . ": slideshow {$params['width']}x{$params['height']}\n"); $slideshowHtml .= Xml::openElement('div', array('class' => 'wikia-slideshow-wrapper', 'style' => 'width: ' . ($this->mWidths + 10) . 'px')); // wrap images inside <div> and <ul> $slideshowHtml .= Xml::openElement('div', array('class' => 'wikia-slideshow-images-wrapper accent')); $slideshowHtml .= Xml::openElement('ul', array('class' => 'wikia-slideshow-images neutral', 'style' => "height: {$params['height']}px; width: {$params['width']}px")); $index = 0; foreach ($this->mFiles as $p => $pair) { /** * @var $nt Title */ $nt = $pair[0]; $text = $pair[1]; $link = $pair[2]; # Give extensions a chance to select the file revision for us $time = $descQuery = false; wfRunHooks('BeforeGalleryFindFile', array(&$this, &$nt, &$time, &$descQuery)); $img = wfFindFile($nt, $time); if (WikiaFileHelper::isFileTypeVideo($img)) { continue; } $thumb = null; // let's properly scale image (don't make it bigger than original size) and handle "crop" attribute if (is_object($img) && $nt->getNamespace() == NS_FILE) { $thumbParams = WikiaPhotoGalleryHelper::getThumbnailDimensions($img, $params['width'], $params['height'], $this->mCrop); } $caption = $linkOverlay = ''; // render caption overlay if ($text != '') { $caption = Xml::openElement('span', array('class' => 'wikia-slideshow-image-caption')) . Xml::openElement('span', array('class' => 'wikia-slideshow-image-caption-inner')) . $text . Xml::closeElement('span') . Xml::closeElement('span'); } // parse link $linkAttribs = $this->parseLink($nt->getLocalUrl(), $nt->getText(), $link); // extra link tag attributes $linkAttribs['id'] = "{$id}-{$index}"; $linkAttribs['style'] = 'width: ' . ($params['width'] - 80) . 'px'; if ($link == '') { // tooltip to be used for not-linked images $linkAttribs['title'] = wfMessage('wikiaPhotoGallery-slideshow-view-popout-tooltip')->text(); $linkAttribs['class'] = 'wikia-slideshow-image'; unset($linkAttribs['href']); } else { // linked images $linkAttribs['class'] .= ' wikia-slideshow-image'; // support |linktext= syntax if ($this->mData['images'][$p]['linktext'] != '') { $linkText = $this->mData['images'][$p]['linktext']; } else { $linkText = $link; } // add link overlay $linkOverlay = Xml::openElement('span', array('class' => 'wikia-slideshow-link-overlay')) . wfMessage('wikiaPhotoGallery-slideshow-view-link-overlay', Sanitizer::removeHTMLtags($linkText))->text() . Xml::closeElement('span'); } // generate HTML for a single slideshow image $thumbHtml = null; $liAttribs = array('title' => null); if ($nt->getNamespace() != NS_FILE || !$img) { # We're dealing with a non-image, spit out the name and be done with it. $thumbHtml = '<a class="image broken-image new" style="line-height: ' . $this->mHeights . 'px;">' . $nt->getText() . '</a>'; } elseif ($this->mHideBadImages && wfIsBadImage($nt->getDBkey(), $this->getContextTitle())) { # The image is blacklisted, just show it as a text link. $thumbHtml = '<div style="height: ' . ($this->mHeights * 1.25 + 2) . 'px;">' . $sk->makeKnownLinkObj($nt, $nt->getText()) . '</div>'; } elseif (!($thumb = $img->transform($thumbParams))) { # Error generating thumbnail. $thumbHtml = '<div style="height: ' . ($this->mHeights * 1.25 + 2) . 'px;">' . htmlspecialchars($img->getLastError()) . '</div>'; } else { $thumbAttribs = array('data-src' => $thumb->url, 'class' => 'thumbimage', 'width' => $thumb->width, 'height' => $thumb->height, 'style' => 'border: 0px;', 'data-image-name' => $img->getTitle()->getText(), 'data-image-key' => $img->getTitle()->getDBKey()); if (!empty($this->mData['images'][$p]['data-caption'])) { $thumbAttribs['data-caption'] = $this->mData['images'][$p]['data-caption']; } $thumbHtml = Xml::element('img', $thumbAttribs); } // add CSS class so we can show first slideshow image before JS is loaded if ($index == 0) { $liAttribs['class'] = 'wikia-slideshow-first-image'; } $slideshowHtml .= Xml::openElement('li', $liAttribs) . $thumbHtml . Xml::element('a', $linkAttribs, ' ') . $caption . $linkOverlay . '</li>'; $index++; // Call parser transform hook if ($this->mParser && is_object($img) && $img->getHandler()) { $img->getHandler()->parserTransformHook($this->mParser, $img); } if (is_object($thumb)) { wfDebug(__METHOD__ . ": image '" . $nt->getText() . "' {$thumb->width}x{$thumb->height}\n"); } } $slideshowHtml .= Xml::closeElement('ul'); $slideshowHtml .= Xml::closeElement('div'); // render prev/next buttons global $wgBlankImgUrl; $top = ($params['height'] >> 1) - 30 + 5; $slideshowHtml .= Xml::openElement('div', array('class' => 'wikia-slideshow-prev-next')); // prev $slideshowHtml .= Xml::openElement('a', array('class' => 'wikia-slideshow-sprite wikia-slideshow-prev', 'style' => "top: {$top}px", 'title' => wfMessage('wikiaPhotoGallery-slideshow-view-prev-tooltip')->text())); $slideshowHtml .= Xml::openElement('span'); $slideshowHtml .= Xml::element('img', array('class' => 'chevron', 'src' => $wgBlankImgUrl)); $slideshowHtml .= Xml::closeElement('span'); $slideshowHtml .= Xml::closeElement('a'); // next $slideshowHtml .= Xml::openElement('a', array('class' => 'wikia-slideshow-sprite wikia-slideshow-next', 'style' => "top: {$top}px", 'title' => wfMessage('wikiaPhotoGallery-slideshow-view-next-tooltip')->text())); $slideshowHtml .= Xml::openElement('span'); $slideshowHtml .= Xml::element('img', array('class' => 'chevron', 'src' => $wgBlankImgUrl)); $slideshowHtml .= Xml::closeElement('span'); $slideshowHtml .= Xml::closeElement('a'); $slideshowHtml .= Xml::closeElement('div'); // render slideshow toolbar $slideshowHtml .= Xml::openElement('div', array('class' => 'wikia-slideshow-toolbar clearfix', 'style' => 'display: none')); // Pop-out icon, "X of X" counter $counterValue = wfMessage('wikiaPhotoGallery-slideshow-view-number', '$1', $index)->text(); $slideshowHtml .= Xml::openElement('div', array('style' => 'float: left')); $slideshowHtml .= Xml::element('img', array('class' => 'wikia-slideshow-popout lightbox', 'height' => 11, 'src' => "{$wgStylePath}/common/images/magnify-clip.png", 'title' => wfMessage('wikiaPhotoGallery-slideshow-view-popout-tooltip')->text(), 'width' => 15)); $slideshowHtml .= Xml::element('span', array('class' => 'wikia-slideshow-toolbar-counter', 'data-counter' => $counterValue), str_replace('$1', '1', $counterValue)); $slideshowHtml .= Xml::closeElement('div'); // "Add Image" if (!empty($this->mShowAddButton)) { $slideshowHtml .= Xml::element('a', array('class' => 'wikia-slideshow-addimage wikia-button secondary', 'style' => 'float: right'), wfMessage('wikiaPhotoGallery-slideshow-view-addphoto')->inContentLanguage()->text()); } $slideshowHtml .= Xml::closeElement('div'); // close slideshow wrapper $slideshowHtml .= Xml::closeElement('div'); $slideshowHtml .= Xml::closeElement('div'); // output JS to init slideshow $width = "{$params['width']}px"; $height = "{$params['height']}px"; $slideshowHtml .= JSSnippets::addToStack(array('wikia_photo_gallery_slideshow_js', 'wikia_photo_gallery_slideshow_scss'), array(), 'WikiaPhotoGallerySlideshow.init', array('id' => $id, 'width' => $width, 'height' => $height)); } wfProfileOut(__METHOD__); return $slideshowHtml; }
/** * Return a HTML representation of the image gallery * * For each image in the gallery, display * - a thumbnail * - the image name * - the additional text provided when adding the image * - the size of the image * * @return string */ function toHTML() { if ($this->mPerRow > 0) { $maxwidth = $this->mPerRow * ($this->mWidths + self::THUMB_PADDING + self::GB_PADDING + self::GB_BORDERS); $oldStyle = isset($this->mAttribs['style']) ? $this->mAttribs['style'] : ''; # _width is ignored by any sane browser. IE6 doesn't know max-width so it uses _width instead $this->mAttribs['style'] = "max-width: {$maxwidth}px;_width: {$maxwidth}px;" . $oldStyle; } $attribs = Sanitizer::mergeAttributes(array('class' => 'gallery'), $this->mAttribs); $output = Xml::openElement('ul', $attribs); if ($this->mCaption) { $output .= "\n\t<li class='gallerycaption'>{$this->mCaption}</li>"; } $lang = $this->getLang(); $params = array('width' => $this->mWidths, 'height' => $this->mHeights); # Output each image... foreach ($this->mImages as $pair) { $nt = $pair[0]; $text = $pair[1]; # "text" means "caption" here $alt = $pair[2]; $link = $pair[3]; $descQuery = false; if ($nt->getNamespace() == NS_FILE) { # Get the file... if ($this->mParser instanceof Parser) { # Give extensions a chance to select the file revision for us $options = array(); wfRunHooks('BeforeParserFetchFileAndTitle', array($this->mParser, $nt, &$options, &$descQuery)); # Fetch and register the file (file title may be different via hooks) list($img, $nt) = $this->mParser->fetchFileAndTitle($nt, $options); } else { $img = wfFindFile($nt); } } else { $img = false; } if (!$img) { # We're dealing with a non-image, spit out the name and be done with it. $thumbhtml = "\n\t\t\t" . '<div style="height: ' . (self::THUMB_PADDING + $this->mHeights) . 'px;">' . htmlspecialchars($nt->getText()) . '</div>'; } elseif ($this->mHideBadImages && wfIsBadImage($nt->getDBkey(), $this->getContextTitle())) { # The image is blacklisted, just show it as a text link. $thumbhtml = "\n\t\t\t" . '<div style="height: ' . (self::THUMB_PADDING + $this->mHeights) . 'px;">' . Linker::link($nt, htmlspecialchars($nt->getText()), array(), array(), array('known', 'noclasses')) . '</div>'; } elseif (!($thumb = $img->transform($params))) { # Error generating thumbnail. $thumbhtml = "\n\t\t\t" . '<div style="height: ' . (self::THUMB_PADDING + $this->mHeights) . 'px;">' . htmlspecialchars($img->getLastError()) . '</div>'; } else { $vpad = (self::THUMB_PADDING + $this->mHeights - $thumb->height) / 2; $imageParameters = array('desc-link' => true, 'desc-query' => $descQuery, 'alt' => $alt, 'custom-url-link' => $link); # In the absence of both alt text and caption, fall back on providing screen readers with the filename as alt text if ($alt == '' && $text == '') { $imageParameters['alt'] = $nt->getText(); } # Set both fixed width and min-height. $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="width: ' . ($this->mWidths + self::THUMB_PADDING) . 'px;">' . '<div style="margin:' . $vpad . 'px auto;">' . $thumb->toHtml($imageParameters) . '</div></div>'; // Call parser transform hook if ($this->mParser && $img->getHandler()) { $img->getHandler()->parserTransformHook($this->mParser, $img); } } //TODO // $linkTarget = Title::newFromText( $wgContLang->getNsText( MWNamespace::getUser() ) . ":{$ut}" ); // $ul = Linker::link( $linkTarget, $ut ); if ($this->mShowBytes) { if ($img) { $fileSize = htmlspecialchars($lang->formatSize($img->getSize())); } else { $fileSize = wfMessage('filemissing')->escaped(); } $fileSize = "{$fileSize}<br />\n"; } else { $fileSize = ''; } $textlink = $this->mShowFilename ? Linker::link($nt, htmlspecialchars($lang->truncate($nt->getText(), $this->mCaptionLength)), array(), array(), array('known', 'noclasses')) . "<br />\n" : ''; # ATTENTION: The newline after <div class="gallerytext"> is needed to accommodate htmltidy which # in version 4.8.6 generated crackpot html in its absence, see: # http://bugzilla.wikimedia.org/show_bug.cgi?id=1765 -Ævar # Weird double wrapping (the extra div inside the li) needed due to FF2 bug # Can be safely removed if FF2 falls completely out of existence $output .= "\n\t\t" . '<li class="gallerybox" style="width: ' . ($this->mWidths + self::THUMB_PADDING + self::GB_PADDING) . 'px">' . '<div style="width: ' . ($this->mWidths + self::THUMB_PADDING + self::GB_PADDING) . 'px">' . $thumbhtml . "\n\t\t\t" . '<div class="gallerytext">' . "\n" . $textlink . $text . $fileSize . "\n\t\t\t</div>" . "\n\t\t</div></li>"; } $output .= "\n</ul>"; return $output; }
/** * @dataProvider provideWfIsBadImageList * @covers ::wfIsBadImage */ public function testWfIsBadImage($name, $title, $blacklist, $expected, $desc) { $this->assertEquals($expected, wfIsBadImage($name, $title, $blacklist), $desc); }
/** * Return a HTML representation of the image gallery * * For each image in the gallery, display * - a thumbnail * - the image name * - the additional text provided when adding the image * - the size of the image * * @return string */ function toHTML() { if ( $this->mPerRow > 0 ) { $maxwidth = $this->mPerRow * ( $this->mWidths + $this->getAllPadding() ); $oldStyle = isset( $this->mAttribs['style'] ) ? $this->mAttribs['style'] : ''; # _width is ignored by any sane browser. IE6 doesn't know max-width so it uses _width instead $this->mAttribs['style'] = "max-width: {$maxwidth}px;_width: {$maxwidth}px;" . $oldStyle; } $attribs = Sanitizer::mergeAttributes( array( 'class' => 'gallery mw-gallery-' . $this->mMode ), $this->mAttribs ); $modules = $this->getModules(); if ( $this->mParser ) { $this->mParser->getOutput()->addModules( $modules ); } else { $this->getOutput()->addModules( $modules ); } $output = Xml::openElement( 'ul', $attribs ); if ( $this->mCaption ) { $output .= "\n\t<li class='gallerycaption'>{$this->mCaption}</li>"; } $lang = $this->getRenderLang(); # Output each image... foreach ( $this->mImages as $pair ) { $nt = $pair[0]; $text = $pair[1]; # "text" means "caption" here $alt = $pair[2]; $link = $pair[3]; $descQuery = false; if ( $nt->getNamespace() === NS_FILE ) { # Get the file... if ( $this->mParser instanceof Parser ) { # Give extensions a chance to select the file revision for us $options = array(); wfRunHooks( 'BeforeParserFetchFileAndTitle', array( $this->mParser, $nt, &$options, &$descQuery ) ); # Fetch and register the file (file title may be different via hooks) list( $img, $nt ) = $this->mParser->fetchFileAndTitle( $nt, $options ); } else { $img = wfFindFile( $nt ); } } else { $img = false; } $params = $this->getThumbParams( $img ); // $pair[4] is per image handler options $transformOptions = $params + $pair[4]; $thumb = false; if ( !$img ) { # We're dealing with a non-image, spit out the name and be done with it. $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' . ( $this->getThumbPadding() + $this->mHeights ) . 'px;">' . htmlspecialchars( $nt->getText() ) . '</div>'; if ( $this->mParser instanceof Parser ) { $this->mParser->addTrackingCategory( 'broken-file-category' ); } } elseif ( $this->mHideBadImages && wfIsBadImage( $nt->getDBkey(), $this->getContextTitle() ) ) { # The image is blacklisted, just show it as a text link. $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' . ( $this->getThumbPadding() + $this->mHeights ) . 'px;">' . Linker::link( $nt, htmlspecialchars( $nt->getText() ), array(), array(), array( 'known', 'noclasses' ) ) . '</div>'; } elseif ( !( $thumb = $img->transform( $transformOptions ) ) ) { # Error generating thumbnail. $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' . ( $this->getThumbPadding() + $this->mHeights ) . 'px;">' . htmlspecialchars( $img->getLastError() ) . '</div>'; } else { $vpad = $this->getVPad( $this->mHeights, $thumb->getHeight() ); $imageParameters = array( 'desc-link' => true, 'desc-query' => $descQuery, 'alt' => $alt, 'custom-url-link' => $link ); # In the absence of both alt text and caption, fall back on providing screen readers with the filename as alt text if ( $alt == '' && $text == '' ) { $imageParameters['alt'] = $nt->getText(); } $this->adjustImageParameters( $thumb, $imageParameters ); # Set both fixed width and min-height. $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="width: ' . $this->getThumbDivWidth( $thumb->getWidth() ) . 'px;">' # Auto-margin centering for block-level elements. Needed now that we have video # handlers since they may emit block-level elements as opposed to simple <img> tags. # ref http://css-discuss.incutio.com/?page=CenteringBlockElement . '<div style="margin:' . $vpad . 'px auto;">' . $thumb->toHtml( $imageParameters ) . '</div></div>'; // Call parser transform hook if ( $this->mParser && $img->getHandler() ) { $img->getHandler()->parserTransformHook( $this->mParser, $img ); } } //TODO // $linkTarget = Title::newFromText( $wgContLang->getNsText( MWNamespace::getUser() ) . ":{$ut}" ); // $ul = Linker::link( $linkTarget, $ut ); if ( $this->mShowBytes ) { if ( $img ) { $fileSize = htmlspecialchars( $lang->formatSize( $img->getSize() ) ); } else { $fileSize = $this->msg( 'filemissing' )->escaped(); } $fileSize = "$fileSize<br />\n"; } else { $fileSize = ''; } $textlink = $this->mShowFilename ? Linker::link( $nt, htmlspecialchars( $lang->truncate( $nt->getText(), $this->mCaptionLength ) ), array(), array(), array( 'known', 'noclasses' ) ) . "<br />\n" : ''; $galleryText = $textlink . $text . $fileSize; $galleryText = $this->wrapGalleryText( $galleryText, $thumb ); # Weird double wrapping (the extra div inside the li) needed due to FF2 bug # Can be safely removed if FF2 falls completely out of existence $output .= "\n\t\t" . '<li class="gallerybox" style="width: ' . $this->getGBWidth( $thumb ) . 'px">' . '<div style="width: ' . $this->getGBWidth( $thumb ) . 'px">' . $thumbhtml . $galleryText . "\n\t\t</div></li>"; } $output .= "\n</ul>"; return $output; }
/** * Return a HTML representation of the image gallery * * For each image in the gallery, display * - a thumbnail * - the image name * - the additional text provided when adding the image * - the size of the image * */ function toHTML() { global $wgLang; $sk = $this->getSkin(); if ($this->mPerRow > 0) { $maxwidth = $this->mPerRow * ($this->mWidths + self::THUMB_PADDING + self::GB_PADDING + self::GB_BORDERS); $oldStyle = isset($this->mAttribs['style']) ? $this->mAttribs['style'] : ""; $this->mAttribs['style'] = "max-width: {$maxwidth}px;_width: {$maxwidth}px;" . $oldStyle; } $attribs = Sanitizer::mergeAttributes(array('class' => 'gallery'), $this->mAttribs); $s = Xml::openElement('ul', $attribs); if ($this->mCaption) { $s .= "\n\t<li class='gallerycaption'>{$this->mCaption}</li>"; } $params = array('width' => $this->mWidths, 'height' => $this->mHeights); $i = 0; foreach ($this->mImages as $pair) { $nt = $pair[0]; $text = $pair[1]; # "text" means "caption" here # Give extensions a chance to select the file revision for us $time = $descQuery = false; wfRunHooks('BeforeGalleryFindFile', array(&$this, &$nt, &$time, &$descQuery)); if ($nt->getNamespace() == NS_FILE) { $img = wfFindFile($nt, array('time' => $time)); } else { $img = false; } if (!$img) { # We're dealing with a non-image, spit out the name and be done with it. $thumbhtml = "\n\t\t\t" . '<div style="height: ' . (self::THUMB_PADDING + $this->mHeights) . 'px;">' . htmlspecialchars($nt->getText()) . '</div>'; } elseif ($this->mHideBadImages && wfIsBadImage($nt->getDBkey(), $this->getContextTitle())) { # The image is blacklisted, just show it as a text link. $thumbhtml = "\n\t\t\t" . '<div style="height: ' . (self::THUMB_PADDING + $this->mHeights) . 'px;">' . $sk->link($nt, htmlspecialchars($nt->getText()), array(), array(), array('known', 'noclasses')) . '</div>'; } elseif (!($thumb = $img->transform($params))) { # Error generating thumbnail. $thumbhtml = "\n\t\t\t" . '<div style="height: ' . (self::THUMB_PADDING + $this->mHeights) . 'px;">' . htmlspecialchars($img->getLastError()) . '</div>'; } else { //We get layout problems with the margin, if the image is smaller //than the line-height, so we less margin in these cases. $minThumbHeight = $thumb->height > 17 ? $thumb->height : 17; $vpad = floor((self::THUMB_PADDING + $this->mHeights - $minThumbHeight) / 2); $imageParameters = array('desc-link' => true, 'desc-query' => $descQuery); # In the absence of a caption, fall back on providing screen readers with the filename as alt text if ($text == '') { $imageParameters['alt'] = $nt->getText(); } # Set both fixed width and min-height. $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="width: ' . ($this->mWidths + self::THUMB_PADDING) . 'px;">' . '<div style="margin:' . $vpad . 'px auto;">' . $thumb->toHtml($imageParameters) . '</div></div>'; // Call parser transform hook if ($this->mParser && $img->getHandler()) { $img->getHandler()->parserTransformHook($this->mParser, $img); } } //TODO // $linkTarget = Title::newFromText( $wgContLang->getNsText( MWNamespace::getUser() ) . ":{$ut}" ); // $ul = $sk->link( $linkTarget, $ut ); if ($this->mShowBytes) { if ($img) { $nb = wfMsgExt('nbytes', array('parsemag', 'escape'), $wgLang->formatNum($img->getSize())); } else { $nb = wfMsgHtml('filemissing'); } $nb = "{$nb}<br />\n"; } else { $nb = ''; } $textlink = $this->mShowFilename ? $sk->link($nt, htmlspecialchars($wgLang->truncate($nt->getText(), $this->mCaptionLength)), array(), array(), array('known', 'noclasses')) . "<br />\n" : ''; # ATTENTION: The newline after <div class="gallerytext"> is needed to accommodate htmltidy which # in version 4.8.6 generated crackpot html in its absence, see: # http://bugzilla.wikimedia.org/show_bug.cgi?id=1765 -Ævar # Weird double wrapping in div needed due to FF2 bug # Can be safely removed if FF2 falls completely out of existance $s .= "\n\t\t" . '<li class="gallerybox" style="width: ' . ($this->mWidths + self::THUMB_PADDING + self::GB_PADDING) . 'px">' . '<div style="width: ' . ($this->mWidths + self::THUMB_PADDING + self::GB_PADDING) . 'px">' . $thumbhtml . "\n\t\t\t" . '<div class="gallerytext">' . "\n" . $textlink . $text . $nb . "\n\t\t\t</div>" . "\n\t\t</div></li>"; ++$i; } $s .= "\n</ul>"; return $s; }
private function photoToHTML($img, $nt, $text = '', $alt = '', $titleLink = null, $descQuery = '') { //Some ugly alignment logic used later $verticalPadding = 0; $horizontalPadding = 0; $params = array('width' => $this->mPhotoWidth, 'height' => $this->mPhotoHeight); if (!$img) { $html = '<div class="CarError" style="height: ' . $params['height'] . 'px; width: ' . $params['width'] . 'px;">' . htmlspecialchars($nt->getText()) . '</div>'; } else { if ($this->mHideBadImages && wfIsBadImage($nt->getDBkey(), $this->getContextTitle())) { $html = '<div class="CarError" style="height: ' . $params['height'] . 'px; width: ' . $params['width'] . 'px;">' . Linker::link($nt, htmlspecialchars($nt->getText()), array(), array(), array('known', 'noclasses')) . '</div>'; } else { if (!($thumb = $img->transform($params))) { # Error generating thumbnail. $html = '<div class="CarError" style="height: ' . $params['height'] . 'px; width: ' . $params['width'] . 'px;">' . htmlspecialchars($img->getLastError()) . '</div>'; } else { $imageParameters = array('desc-link' => true, 'desc-query' => $descQuery, 'alt' => $alt, 'custom-title-link' => $titleLink); # In the absence of both alt text and caption, fall back on providing screen readers with the filename as alt text if ($alt == '') { if ($text == '') { $imageParameters['alt'] = $nt->getText(); } else { $imageParameters['alt'] = htmlspecialchars($text); } } $html = $thumb->toHtml($imageParameters); //Some ugly alignment logic $thumbHeight = $thumb->getHeight(); $thumbWidth = $thumb->getWidth(); if ($this->mPhotoHeight > $thumbHeight) { $verticalPadding = floor(($this->mPhotoHeight - $thumbHeight) / 2); } if ($this->mPhotoWidth > $thumbWidth) { $horizontalPadding = floor(($this->mPhotoWidth - $thumbWidth) / 2); } // Call parser transform hook if ($this->mParser && $img->getHandler()) { $img->getHandler()->parserTransformHook($this->mParser, $img); } } } } $wrapperHeight = $this->mPhotoHeight - 2 * $verticalPadding + 2; $wrapperWidth = $this->mPhotoWidth - 2 * $horizontalPadding + 2; $html = Html::rawElement('div', array('class' => 'wrapper', 'style' => 'height:' . $wrapperHeight . 'px; width:' . $wrapperWidth . 'px; padding:' . $verticalPadding . 'px ' . $horizontalPadding . 'px;'), $html); $html .= Html::rawElement('div', array('class' => 'caption'), $text); return $html; }
/** * Process [[ ]] wikilinks (RIL) * @return LinkHolderArray * * @private */ function replaceInternalLinks2(&$s) { wfProfileIn(__METHOD__); # RTE (Rich Text Editor) - begin # @author: Inez Korczyński global $wgRTEParserEnabled; # RTE (Rich Text Editor) - end wfProfileIn(__METHOD__ . '-setup'); static $tc = FALSE, $e1, $e1_img; # the % is needed to support urlencoded titles as well if (!$tc) { $tc = Title::legalChars() . '#%'; # Match a link having the form [[namespace:link|alternate]]trail $e1 = "/^([{$tc}]+)(?:\\|(.+?))?]](.*)\$/sD"; # Match cases where there is no "]]", which might still be images $e1_img = "/^([{$tc}]+)\\|(.*)\$/sD"; } $holders = new LinkHolderArray($this); # split the entire text string on occurences of [[ $a = StringUtils::explode('[[', ' ' . $s); # get the first element (all text up to first [[), and remove the space we added $s = $a->current(); $a->next(); $line = $a->current(); # Workaround for broken ArrayIterator::next() that returns "void" $s = substr($s, 1); $useLinkPrefixExtension = $this->getTargetLanguage()->linkPrefixExtension(); $e2 = null; if ($useLinkPrefixExtension) { # Match the end of a line for a word that's not followed by whitespace, # e.g. in the case of 'The Arab al[[Razi]]', 'al' will be matched $e2 = wfMsgForContent('linkprefix'); } if (is_null($this->mTitle)) { wfProfileOut(__METHOD__ . '-setup'); wfProfileOut(__METHOD__); throw new MWException(__METHOD__ . ": \$this->mTitle is null\n"); } $nottalk = !$this->mTitle->isTalkPage(); if ($useLinkPrefixExtension) { $m = array(); if (preg_match($e2, $s, $m)) { $first_prefix = $m[2]; } else { $first_prefix = false; } } else { $prefix = ''; } if ($this->getConverterLanguage()->hasVariants()) { $selflink = $this->getConverterLanguage()->autoConvertToAllVariants($this->mTitle->getPrefixedText()); } else { $selflink = array($this->mTitle->getPrefixedText()); } $useSubpages = $this->areSubpagesAllowed(); wfProfileOut(__METHOD__ . '-setup'); # Loop for each link for (; $line !== false && $line !== null; $a->next(), $line = $a->current()) { # Check for excessive memory usage if ($holders->isBig()) { # Too big # Do the existence check, replace the link holders and clear the array $holders->replace($s); $holders->clear(); } # RTE (Rich Text Editor) - begin # @author: Inez Korczyński if (!empty($wgRTEParserEnabled)) { $RTE_wikitextIdx = RTEMarker::getDataIdx(RTEMarker::INTERNAL_WIKITEXT, $line); // decode entities inside links wikimarkup (RT #38844) if ($pos = strpos($line, ']]')) { // unmark entities inside link $link = substr($line, 0, $pos); $link = RTEParser::unmarkEntities($link); // leave the rest of the line untouched $line = $link . substr($line, $pos); } } # RTE - end if ($useLinkPrefixExtension) { wfProfileIn(__METHOD__ . '-prefixhandling'); if (preg_match($e2, $s, $m)) { $prefix = $m[2]; $s = $m[1]; } else { $prefix = ''; } # first link if ($first_prefix) { $prefix = $first_prefix; $first_prefix = false; } wfProfileOut(__METHOD__ . '-prefixhandling'); } $might_be_img = false; wfProfileIn(__METHOD__ . "-e1"); if (preg_match($e1, $line, $m)) { # page with normal text or alt $text = $m[2]; # If we get a ] at the beginning of $m[3] that means we have a link that's something like: # [[Image:Foo.jpg|[http://example.com desc]]] <- having three ] in a row f***s up, # the real problem is with the $e1 regex # See bug 1300. # # Still some problems for cases where the ] is meant to be outside punctuation, # and no image is in sight. See bug 2095. # if ($text !== '' && substr($m[3], 0, 1) === ']' && strpos($text, '[') !== false) { $text .= ']'; # so that replaceExternalLinks($text) works later $m[3] = substr($m[3], 1); } # fix up urlencoded title texts if (strpos($m[1], '%') !== false) { # Should anchors '#' also be rejected? $m[1] = str_replace(array('<', '>'), array('<', '>'), rawurldecode($m[1])); } $trail = $m[3]; } elseif (preg_match($e1_img, $line, $m)) { # Invalid, but might be an image with a link in its caption $might_be_img = true; $text = $m[2]; if (strpos($m[1], '%') !== false) { $m[1] = rawurldecode($m[1]); } $trail = ""; } else { # Invalid form; output directly $s .= $prefix . '[[' . $line; wfProfileOut(__METHOD__ . "-e1"); continue; } wfProfileOut(__METHOD__ . "-e1"); wfProfileIn(__METHOD__ . "-misc"); # Don't allow internal links to pages containing # PROTO: where PROTO is a valid URL protocol; these # should be external links. if (preg_match('/^(?:' . wfUrlProtocols() . ')/', $m[1])) { $s .= $prefix . '[[' . $line; wfProfileOut(__METHOD__ . "-misc"); continue; } # Make subpage if necessary if ($useSubpages) { $link = $this->maybeDoSubpageLink($m[1], $text); } else { $link = $m[1]; } $noforce = substr($m[1], 0, 1) !== ':'; if (!$noforce) { # Strip off leading ':' $link = substr($link, 1); } wfProfileOut(__METHOD__ . "-misc"); wfProfileIn(__METHOD__ . "-title"); $nt = Title::newFromText($this->mStripState->unstripNoWiki($link)); if ($nt === null) { $s .= $prefix . '[[' . $line; wfProfileOut(__METHOD__ . "-title"); continue; } $ns = $nt->getNamespace(); $iw = $nt->getInterWiki(); wfProfileOut(__METHOD__ . "-title"); if ($might_be_img) { # if this is actually an invalid link wfProfileIn(__METHOD__ . "-might_be_img"); if (($ns == NS_FILE || $ns == NS_VIDEO) && $noforce) { # but might be an image $found = false; while (true) { # look at the next 'line' to see if we can close it there $a->next(); $next_line = $a->current(); if ($next_line === false || $next_line === null) { break; } $m = explode(']]', $next_line, 3); if (count($m) == 3) { # the first ]] closes the inner link, the second the image $found = true; $text .= "[[{$m[0]}]]{$m[1]}"; $trail = $m[2]; break; } elseif (count($m) == 2) { # if there's exactly one ]] that's fine, we'll keep looking $text .= "[[{$m[0]}]]{$m[1]}"; } else { # if $next_line is invalid too, we need look no further $text .= '[[' . $next_line; break; } } if (!$found) { # we couldn't find the end of this imageLink, so output it raw # but don't ignore what might be perfectly normal links in the text we've examined $holders->merge($this->replaceInternalLinks2($text)); $s .= "{$prefix}[[{$link}|{$text}"; # note: no $trail, because without an end, there *is* no trail wfProfileOut(__METHOD__ . "-might_be_img"); continue; } } else { # it's not an image, so output it raw $s .= "{$prefix}[[{$link}|{$text}"; # note: no $trail, because without an end, there *is* no trail wfProfileOut(__METHOD__ . "-might_be_img"); continue; } wfProfileOut(__METHOD__ . "-might_be_img"); } $wasblank = $text == ''; if ($wasblank) { $text = $link; } else { # Bug 4598 madness. Handle the quotes only if they come from the alternate part # [[Lista d''e paise d''o munno]] -> <a href="...">Lista d''e paise d''o munno</a> # [[Criticism of Harry Potter|Criticism of ''Harry Potter'']] # -> <a href="Criticism of Harry Potter">Criticism of <i>Harry Potter</i></a> $text = $this->doQuotes($text); } # Link not escaped by : , create the various objects if ($noforce) { global $wgContLang; # Interwikis if (empty($wgRTEParserEnabled)) { # wikia wfProfileIn(__METHOD__ . "-interwiki"); if ($iw && $this->mOptions->getInterwikiMagic() && $nottalk && $wgContLang->getLanguageName($iw)) { $this->mOutput->addLanguageLink($nt->getFullText()); $s = rtrim($s . $prefix); $s .= trim($trail, "\n") == '' ? '' : $prefix . $trail; wfProfileOut(__METHOD__ . "-interwiki"); continue; } wfProfileOut(__METHOD__ . "-interwiki"); } # wikia if ($ns == NS_FILE) { wfProfileIn(__METHOD__ . "-image"); if (!wfIsBadImage($nt->getDBkey(), $this->mTitle)) { if ($wasblank) { # if no parameters were passed, $text # becomes something like "File:Foo.png", # which we don't want to pass on to the # image generator $text = ''; } else { # recursively parse links inside the image caption # actually, this will parse them in any other parameters, too, # but it might be hard to fix that, and it doesn't matter ATM $text = $this->replaceExternalLinks($text); $holders->merge($this->replaceInternalLinks2($text)); } # RTE (Rich Text Editor) - begin # @author: Inez Korczyński if (!empty($wgRTEParserEnabled)) { $text = RTEMarker::generate(RTEMarker::IMAGE_DATA, $RTE_wikitextIdx) . $text; } # RTE - end # cloak any absolute URLs inside the image markup, so replaceExternalLinks() won't touch them /** wikia $s .= $prefix . $this->armorLinks( $this->makeImage( $nt, $text, $holders ) ) . $trail; wikia **/ # cater for new placeholder-in-template namespace - Bartek # TODO: Get the hell out with this code from here this can be done in hook handler fired in makeImage function - Inez if ("Template Placeholder" != $nt->getText()) { $s .= $prefix . $this->armorLinks($this->makeImage($nt, $text, $holders)) . $trail; } else { $s .= $prefix . $this->armorLinks(ImagePlaceholder_makeDullImage($nt, $text, $holders)) . $trail; } } else { $s .= $prefix . $trail; } wfProfileOut(__METHOD__ . "-image"); continue; } if ($ns == NS_CATEGORY) { wfProfileIn(__METHOD__ . "-category"); # RTE (Rich Text Editor) - begin # @author: Inez Korczyński # Category handling if (!empty($wgRTEParserEnabled)) { $dataIdx = RTEData::put('placeholder', array('type' => 'category', 'wikitextIdx' => $RTE_wikitextIdx)); $s .= $prefix . RTEMarker::generate(RTEMarker::PLACEHOLDER, $dataIdx) . $trail; } else { $s = rtrim($s . "\n"); # bug 87 if ($wasblank) { $sortkey = $this->getDefaultSort(); } else { $sortkey = $text; } $sortkey = Sanitizer::decodeCharReferences($sortkey); $sortkey = str_replace("\n", '', $sortkey); $sortkey = $this->getConverterLanguage()->convertCategoryKey($sortkey); $this->mOutput->addCategory($nt->getDBkey(), $sortkey); /** * Strip the whitespace Category links produce, see bug 87 * @todo We might want to use trim($tmp, "\n") here. */ $s .= trim($prefix . $trail, "\n") == '' ? '' : $prefix . $trail; } wfProfileOut(__METHOD__ . "-category"); continue; } /* Wikia change begin - @author: Owen Davis */ /* Support for [[Poll:...]] */ if (defined("NS_WIKIA_POLL") && $ns == NS_WIKIA_POLL) { $poll = WikiaPoll::newFromTitle($nt); if ($poll instanceof WikiaPoll) { # RTE (Rich Text Editor) - begin # @author: Owen Davis if (!empty($wgRTEParserEnabled)) { $s .= $prefix . WikiaPollHooks::generateRTE($poll, $nt, $RTE_wikitextIdx) . $trail; } else { $s .= $prefix . WikiaPollHooks::generate($poll, $nt) . $trail; } # RTE - end continue; } } /* Wikia change end */ } # RTE (Rich Text Editor) - begin # @author: Inez Korczyński # No special handling for self-linking in RTE mode # Self-link checking if (empty($wgRTEParserEnabled) && $nt->getFragment() === '' && $ns != NS_SPECIAL) { if (in_array($nt->getPrefixedText(), $selflink, true)) { $s .= $prefix . Linker::makeSelfLinkObj($nt, $text, '', $trail); continue; } } # RTE - end # NS_MEDIA is a pseudo-namespace for linking directly to a file # @todo FIXME: Should do batch file existence checks, see comment below if ($ns == NS_MEDIA) { # RTE (Rich Text Editor) - begin # @author: macbre # BugId:1694 - handle [[Media:xxx]] as placeholders if (!empty($wgRTEParserEnabled)) { $dataIdx = RTEData::put('placeholder', array('type' => 'media', 'wikitextIdx' => $RTE_wikitextIdx)); $s .= $prefix . RTEMarker::generate(RTEMarker::PLACEHOLDER, $dataIdx) . $trail; continue; } # RTE - end wfProfileIn(__METHOD__ . "-media"); # Give extensions a chance to select the file revision for us $options = array(); $descQuery = false; wfRunHooks('BeforeParserFetchFileAndTitle', array($this, $nt, &$options, &$descQuery)); # Fetch and register the file (file title may be different via hooks) list($file, $nt) = $this->fetchFileAndTitle($nt, $options); # Cloak with NOPARSE to avoid replacement in replaceExternalLinks $s .= $prefix . $this->armorLinks(Linker::makeMediaLinkFile($nt, $file, $text)) . $trail; wfProfileOut(__METHOD__ . "-media"); continue; } wfProfileIn(__METHOD__ . "-always_known"); # RTE (Rich Text Editor) - begin # @author: Inez Korczyński if (!empty($wgRTEParserEnabled)) { $text = RTEMarker::generate(RTEMarker::INTERNAL_DATA, RTEData::put('data', array('type' => 'internal', 'wikitextIdx' => $RTE_wikitextIdx, 'text' => $text, 'link' => $link, 'wasblank' => $wasblank, 'noforce' => $noforce))) . $text; } # RTE - end # Some titles, such as valid special pages or files in foreign repos, should # be shown as bluelinks even though they're not included in the page table # # @todo FIXME: isAlwaysKnown() can be expensive for file links; we should really do # batch file existence checks for NS_FILE and NS_MEDIA if ($iw == '' && $nt->isAlwaysKnown()) { $this->mOutput->addLink($nt); $s .= $this->makeKnownLinkHolder($nt, $text, array(), $trail, $prefix); } else { # Links will be added to the output link list after checking $s .= $holders->makeHolder($nt, $text, array(), $trail, $prefix); } wfProfileOut(__METHOD__ . "-always_known"); } wfProfileOut(__METHOD__); return $holders; }