/**
  * Return a HTML representation of the image gallery
  *
  * The new gallery disables the old perrow control, and automatically fit the gallery to the available space in the browser.
  */
 private function renderGallery()
 {
     wfProfileIn(__METHOD__);
     // do not render empty gallery
     if (empty($this->mFiles)) {
         wfProfileOut(__METHOD__);
         return '';
     }
     // Route to the mobile gallery or the new MediaGallery
     if (F::app()->checkSkin('wikiamobile')) {
         $html = $this->renderWikiaMobileMediaGroup();
         wfProfileOut(__METHOD__);
         return $html;
     } elseif ($this->canRenderMediaGallery()) {
         $html = $this->renderMediaGallery();
         // remove spaces from html produced by mustache template
         $html = trim(preg_replace('/\\n+/', ' ', $html));
         wfProfileOut(__METHOD__);
         return $html;
     }
     /** @var Skin|Linker $skin The skin object falls back to Linker methods via __call */
     $skin = RequestContext::getMain()->getSkin();
     $thumbSize = $this->mWidths;
     $orientation = $this->getParam('orientation');
     $ratio = WikiaPhotoGalleryHelper::getRatioFromOption($orientation);
     $crop = $this->mCrop;
     //calculate height of the biggest image
     $maxHeight = 0;
     $fileObjectsCache = array();
     $heights = array();
     $widths = array();
     $thumbParams = array();
     // loop through the images and get height of the tallest one
     foreach ($this->mFiles as $imageData) {
         $img = $this->getImage($imageData[0]);
         $fileObjectsCache[] = $img;
         if (!empty($img)) {
             // get thumbnail limited only by given width
             if ($img->width > $thumbSize) {
                 $imageHeight = round($img->height * ($thumbSize / $img->width));
                 $imageWidth = $thumbSize;
             } else {
                 $imageHeight = $img->height;
                 $imageWidth = $img->width;
             }
             $heights[] = $imageHeight;
             $widths[] = $imageWidth;
             if ($imageHeight > $maxHeight) {
                 $maxHeight = $imageHeight;
             }
         }
     }
     // calculate height based on gallery width
     $height = round($thumbSize / $ratio);
     if ($orientation == 'none') {
         $this->enableCropping($crop = false);
         // use the biggest height found
         if ($maxHeight > 0) {
             $height = $maxHeight;
         }
         // limit height (RT #59355)
         $height = min($height, $thumbSize);
         // recalculate dimensions (RT #59355)
         foreach ($this->mFiles as $index => $image) {
             if (!empty($heights[$index]) && !empty($widths[$index])) {
                 //fix #59355, min() added to let borders wrap images with smaller width
                 //fix #63886, round ( $tmpFloat ) != floor ( $tmpFloat ) added to check if thumbnail will be generated from proper width
                 $tmpFloat = $widths[$index] * $height / $heights[$index];
                 $widths[$index] = min($widths[$index], floor($tmpFloat));
                 $heights[$index] = min($height, $heights[$index]);
                 if (round($tmpFloat) != floor($tmpFloat)) {
                     $heights[$index]--;
                 }
             } else {
                 $widths[$index] = $thumbSize;
                 $heights[$index] = $height;
             }
         }
     }
     $useBuckets = $this->getParam('buckets');
     $useRowDivider = $this->getParam('rowdivider');
     $captionColor = $this->getParam('captiontextcolor');
     $borderColor = $this->getParam('bordercolor');
     $perRow = $this->mPerRow > 0 ? $this->mPerRow : 'dynamic';
     $position = $this->getParam('position');
     $captionsPosition = $this->getParam('captionposition', 'below');
     $captionsAlign = $this->getParam('captionalign');
     $captionsSize = $this->getParam('captionsize');
     $captionsColor = !empty($captionColor) ? $captionColor : null;
     $spacing = $this->getParam('spacing');
     $borderSize = $this->getParam('bordersize');
     $borderColor = !empty($borderColor) ? $borderColor : 'accent';
     $isTemplate = isset($this->mData['params']['source']) && $this->mData['params']['source'] == "template";
     $hash = $this->mData['hash'];
     $id = 'gallery-' . $this->mData['id'];
     $showAddButton = $this->mShowAddButton == true;
     $hideOverflow = $this->getParam('hideoverflow');
     if (in_array($borderColor, array('accent', 'color1'))) {
         $borderColorClass = " {$borderColor}";
     } else {
         $borderColorCSS = " border-color: {$borderColor};";
         if ($captionsPosition == 'within') {
             $captionsBackgroundColor = $borderColor;
         }
     }
     $html = Xml::openElement('div', array('id' => $id, 'hash' => $hash, 'class' => 'wikia-gallery' . ($isTemplate ? ' template' : null) . " wikia-gallery-caption-{$captionsPosition}" . " wikia-gallery-position-{$position}" . " wikia-gallery-spacing-{$spacing}" . " wikia-gallery-border-{$borderSize}" . " wikia-gallery-captions-{$captionsAlign}" . " wikia-gallery-caption-size-{$captionsSize}"));
     // render gallery caption (RT #59241)
     if ($this->mCaption !== false) {
         $html .= Xml::openElement('div', array('class' => 'wikia-gallery-caption')) . $this->mCaption . Xml::closeElement('div');
     }
     $itemWrapperWidth = $thumbSize;
     $thumbWrapperHeight = $height;
     //compensate image wrapper width depending on the border size
     switch ($borderSize) {
         case 'large':
             $itemWrapperWidth += 10;
             //5px * 2
             $thumbWrapperHeight += 10;
             break;
         case 'medium':
             $itemWrapperWidth += 4;
             //2px * 2
             $thumbWrapperHeight += 4;
             break;
         case 'small':
             $itemWrapperWidth += 2;
             //1px * 2
             $thumbWrapperHeight += 2;
             break;
     }
     //adding more width for the padding
     $outeritemWrapperWidth = $itemWrapperWidth + 20;
     $rowDividerCSS = '';
     if ($useRowDivider) {
         $rowDividerCSS = "height: " . ($thumbWrapperHeight + 100) . "px; padding: 30px 15px 20px 15px; margin: 0px; border-bottom: solid 1px #CCCCCC;";
     }
     if ($useBuckets) {
         $itemSpanStyle = "width:{$outeritemWrapperWidth}px; " . ($useRowDivider ? $rowDividerCSS : 'margin: 4px;');
         $itemDivStyle = "background-color: #f9f9f9; height:{$thumbWrapperHeight}px; text-align: center; border: solid 1px #CCCCCC; padding: " . ($outeritemWrapperWidth - $thumbWrapperHeight) / 2 . "px 5px;";
     } else {
         $itemSpanStyle = "width:{$itemWrapperWidth}px; {$rowDividerCSS}";
         $itemDivStyle = "height:{$thumbWrapperHeight}px;";
     }
     foreach ($this->mFiles as $index => $imageData) {
         if ($perRow != 'dynamic' && $index % $perRow == 0) {
             $html .= Xml::openElement('div', array('class' => 'wikia-gallery-row'));
         }
         $html .= Xml::openElement('div', array('class' => 'wikia-gallery-item', 'style' => $itemSpanStyle));
         $html .= Xml::openElement('div', array('class' => 'thumb', 'style' => $itemDivStyle));
         $image = array();
         // let's properly scale image (don't make it bigger than original size)
         /**
          * @var $imageTitle Title
          * @var $fileObject LocalFile
          */
         $imageTitle = $imageData[0];
         $fileObject = $fileObjectsCache[$index];
         $imageTitleText = $imageTitle->getText();
         $image['height'] = $height;
         $image['width'] = $thumbSize;
         $image['caption'] = $imageData[1];
         if (!is_object($fileObject) || $imageTitle->getNamespace() != NS_FILE) {
             $image['linkTitle'] = $image['titleText'] = $imageTitleText;
             $image['thumbnail'] = false;
             $image['link'] = Skin::makeSpecialUrl("Upload", array('wpDestFile' => $image['linkTitle']));
             $image['classes'] = 'image broken-image accent new';
         } else {
             $thumbParams = WikiaPhotoGalleryHelper::getThumbnailDimensions($fileObject, $thumbSize, $height, $crop);
             $image['thumbnail'] = $fileObject->createThumb($thumbParams['width'], $thumbParams['height']);
             $image['DBKey'] = $fileObject->getTitle()->getDBKey();
             $image['fileTitle'] = $fileObject->getTitle()->getText();
             $image['height'] = $orientation == 'none' ? $heights[$index] : min($thumbParams['height'], $height);
             $imgHeightCompensation = ($height - $image['height']) / 2;
             if ($imgHeightCompensation > 0) {
                 $image['heightCompensation'] = $imgHeightCompensation;
             }
             $image['width'] = min($widths[$index], $thumbSize);
             //Fix #59914, shared.css has auto-alignment rules
             /*$imgWidthCompensation = ($thumbSize - $image['width']) / 2;
             		if ($imgHeightCompensation > 0) $image['widthCompensation'] = $imgWidthCompensation;*/
             $image['link'] = $imageData[2];
             $linkAttribs = $this->parseLink($imageTitle->getLocalUrl(), $imageTitleText, $image['link']);
             $image['link'] = $linkAttribs['href'];
             $image['linkTitle'] = $linkAttribs['title'];
             $image['classes'] = $linkAttribs['class'];
             $image['bytes'] = $fileObject->getSize();
             if ($this->mParser && $fileObject->getHandler()) {
                 $fileObject->getHandler()->parserTransformHook($this->mParser, $fileObject);
             }
         }
         wfRunHooks('GalleryBeforeRenderImage', array(&$image));
         //see Image SEO project
         $wrapperId = preg_replace('/[^a-z0-9_]/i', '-', Sanitizer::escapeId($image['linkTitle']));
         $html .= Xml::openElement('div', array('class' => 'gallery-image-wrapper' . (!$useBuckets && !empty($borderColorClass) ? $borderColorClass : null), 'id' => $wrapperId, 'style' => 'position: relative;' . ($useBuckets ? " width: {$itemWrapperWidth}px; border-style: none;" : " height:{$image['height']}px; width:{$image['width']}px;") . (!empty($image['heightCompensation']) ? " top:{$image['heightCompensation']}px;" : null) . (!empty($borderColorCSS) ? $borderColorCSS : null)));
         $imgStyle = null;
         $isVideo = WikiaFileHelper::isFileTypeVideo($fileObject);
         # Fix 59913 - thumbnail goes as <img /> not as <a> background.
         if ($orientation != 'none') {
             # margin calculation for image positioning
             if ($thumbParams['height'] > $image['height']) {
                 $tempTopMargin = -1 * ($thumbParams['height'] - $image['height']) / 2;
             } else {
                 unset($tempTopMargin);
             }
             if ($thumbParams['width'] > $image['width']) {
                 $tempLeftMargin = -1 * ($thumbParams['width'] - $image['width']) / 2;
             } else {
                 unset($tempLeftMargin);
             }
             $imgStyle = (!empty($tempTopMargin) ? " margin-top:" . $tempTopMargin . "px;" : null) . (!empty($tempLeftMargin) ? " margin-left:" . $tempLeftMargin . "px;" : null);
             if ($isVideo) {
                 $image['classes'] .= ' force-lightbox';
             }
         }
         $linkAttribs = array('class' => empty($image['thumbnail']) ? 'image-no-lightbox' : $image['classes'], 'href' => $image['link'], 'title' => $image['linkTitle'] . (isset($image['bytes']) ? ' (' . $skin->formatSize($image['bytes']) . ')' : ""), 'style' => "height:{$image['height']}px; width:{$image['width']}px;");
         if (!empty($image['thumbnail'])) {
             if ($isVideo) {
                 $thumbHtml = '';
                 $duration = $fileObject->getMetadataDuration();
                 if (!empty($duration)) {
                     $duration = WikiaFileHelper::formatDuration($duration);
                     $thumbHtml .= '<span class="duration">' . $duration . '</span>';
                 }
                 $playButtonSize = ThumbnailHelper::getThumbnailSize($image['width']);
                 $thumbHtml .= $this->videoPlayButton;
                 $linkAttribs['class'] .= ' video video-thumbnail ' . $playButtonSize;
             } else {
                 $thumbHtml = '';
             }
             $imgAttribs = array('style' => (!empty($image['titleText']) ? " line-height:{$image['height']}px;" : null) . $imgStyle, 'src' => $image['thumbnail'] ? $image['thumbnail'] : null, 'title' => $image['linkTitle'] . (isset($image['bytes']) ? ' (' . $skin->formatSize($image['bytes']) . ')' : ""), 'class' => 'thumbimage', 'alt' => preg_replace('/\\.[^\\.]+$/', '', $image['linkTitle']));
             if ($isVideo) {
                 $imgAttribs['data-video-name'] = htmlspecialchars($image['fileTitle']);
                 $imgAttribs['data-video-key'] = urlencode(htmlspecialchars($image['DBKey']));
             } else {
                 $imgAttribs['data-image-name'] = htmlspecialchars($image['fileTitle']);
                 $imgAttribs['data-image-key'] = urlencode(htmlspecialchars($image['DBKey']));
             }
             if (!empty($image['data-caption'])) {
                 $imgAttribs['data-caption'] = $image['data-caption'];
             }
             if (isset($image['thumbnail-classes']) && isset($image['thumbnail-src']) && isset($image['thumbnail-onload'])) {
                 $thumbHtml .= '<noscript>' . Xml::openElement('img', $imgAttribs) . '</noscript>';
                 $imgAttribs['class'] .= ' ' . $image['thumbnail-classes'];
                 $imgAttribs['data-src'] = $imgAttribs['src'];
                 $imgAttribs['src'] = $image['thumbnail-src'];
                 $imgAttribs['onload'] = $image['thumbnail-onload'];
             }
             $thumbHtml .= Xml::openElement('img', $imgAttribs);
         } else {
             $thumbHtml = $image['linkTitle'];
         }
         $html .= Xml::openElement('a', $linkAttribs);
         $html .= $thumbHtml;
         $html .= Xml::closeElement('a');
         if ($captionsPosition == 'below') {
             $html .= Xml::closeElement('div');
             $html .= Xml::closeElement('div');
         }
         // Insert video titles here
         if ($isVideo) {
             $html .= '<div class="title">' . $imageTitleText . '</div>';
         }
         if (!empty($image['caption'])) {
             $html .= Xml::openElement('div', array('class' => 'lightbox-caption' . (!empty($borderColorClass) && $captionsPosition == 'within' ? $borderColorClass : null), 'style' => ($captionsPosition == 'below' ? "width:{$thumbSize}px;" : null) . (!empty($captionsColor) ? " color:{$captionsColor};" : null) . (!empty($captionsBackgroundColor) ? " background-color:{$captionsBackgroundColor}" : null) . ($useBuckets ? " margin-top: 0px;" : '') . (!empty($hideOverflow) ? " overflow: hidden" : null)));
             $html .= $image['caption'];
             $html .= Xml::closeElement('div');
         }
         if ($captionsPosition == 'within') {
             $html .= Xml::closeElement('div');
             $html .= Xml::closeElement('div');
         }
         $html .= Xml::closeElement('div');
         // /div.wikia-gallery-item
         if ($perRow != 'dynamic' && ($index % $perRow == $perRow - 1 || $index == count($this->mFiles) - 1)) {
             $html .= Xml::closeElement('div');
         }
     }
     // "Add image to this gallery" button (this button is shown by JS only in Monaco)
     if ($showAddButton) {
         if ($perRow == 'dynamic') {
             $html .= Xml::element('br');
         }
         // add button for Oasis
         $html .= Xml::openElement('a', array('class' => 'wikia-photogallery-add wikia-button noprint', 'style' => 'display: none'));
         $html .= Xml::element('img', array('src' => F::app()->wg->BlankImgUrl, 'class' => 'sprite photo', 'width' => 26, 'height' => 16));
         $html .= wfMessage('wikiaPhotoGallery-viewmode-addphoto')->inContentLanguage()->text();
         $html .= Xml::closeElement('a');
     }
     $html .= Xml::closeElement('div');
     wfProfileOut(__METHOD__);
     return $html;
 }
 public function getHTML()
 {
     global $wgCategoryExhibitionMediaSectionRows;
     $cachedContent = $this->getFromCache();
     if (empty($cachedContent)) {
         // grabs data for videos and images
         $aTmpData = $this->fetchSectionItems(array(NS_FILE));
         // we wan't old videos
         if (is_array($aTmpData) && count($aTmpData) > 0) {
             $pages = Paginator::newFromArray($aTmpData, $wgCategoryExhibitionMediaSectionRows * 4);
             $pageData = $pages->getPage($this->paginatorPosition, true);
             $aData = array();
             foreach ($pageData as $item) {
                 $itemTitle = Title::newFromID($item['page_id']);
                 $forceHeight = '';
                 $forceWidth = '';
                 $isVideo = WikiaFileHelper::isFileTypeVideo($itemTitle);
                 // item is image
                 $image = wfFindFile($itemTitle);
                 $elementClass = 'lightbox';
                 if (!is_object($image) || $image->height == 0 || $image->width == 0) {
                     $imageSrc = '';
                 } else {
                     $proportions = $image->width / $image->height;
                     if ($proportions < 1) {
                         $calculatedWidth = floor($proportions * $this->thumbWidth);
                     } else {
                         $calculatedWidth = $this->thumbMedia;
                     }
                     $forceWidth = floor($calculatedWidth);
                     $forceHeight = floor($calculatedWidth / $proportions);
                     $imageServing = new ImageServing(array($item['page_id']), $calculatedWidth, array("w" => $image->width, "h" => $image->height));
                     $imageSrc = wfReplaceImageServer($image->getThumbUrl($imageServing->getCut($image->width, $image->height) . "-" . $image->getName()));
                     if ($isVideo) {
                         $videoSizeClass = ThumbnailHelper::getThumbnailSize($forceWidth);
                         $elementClass .= ' video video-thumbnail ' . $videoSizeClass;
                     }
                 }
                 $linkedFiles = $this->getLinkedFiles($itemTitle);
                 if (!empty($linkedFiles)) {
                     $linkText = $linkedFiles->getText();
                     $linkFullUrl = $linkedFiles->getFullURL();
                 } else {
                     $linkText = '';
                     $linkFullUrl = '';
                 }
                 // types casting for proper caching;
                 $aData[] = array('id' => $item['page_id'], 'title' => $itemTitle->getText(), 'key' => $itemTitle->getDBKey(), 'img' => (string) $imageSrc, 'url' => $itemTitle->getFullURL(), 'dimensions' => array('w' => (int) $forceWidth, 'h' => (int) $forceHeight), 'class' => $elementClass, 'data-ref' => $itemTitle->getPrefixedURL(), 'targetUrl' => $linkFullUrl, 'targetText' => $linkText, 'isVideo' => $isVideo);
             }
             $aContent = array('data' => $aData, 'category' => $this->categoryTitle->getText(), 'paginator' => $pages->getBarHTML($this->sUrl));
             $this->saveToCache($aContent);
         } else {
             return false;
         }
     } else {
         $aContent = $cachedContent;
     }
     if (!empty($aContent) && is_array($aContent)) {
         $oTmpl = new EasyTemplate(dirname(__FILE__) . "/templates/");
         $oTmpl->set_vars($aContent);
         $oTmpl->set_vars(array('fromAjax' => $this->isFromAjax));
         if ($this->isFromAjax) {
             return array('page' => $oTmpl->render($this->templateName), 'paginator' => $oTmpl->mVars['paginator']);
         } else {
             return $oTmpl->render($this->templateName);
         }
     }
 }