[], 'values' => [], 'renderLabels' => false ]; foreach ( $groupData as $item ) { $data = $item[ 'data' ]; if ( $item[ 'type' ] === 'data' ) { array_push( $horizontalGroupData[ 'labels' ], $data[ 'label' ] ); array_push( $horizontalGroupData[ 'values' ], $data[ 'value' ] ); if ( !empty( $data[ 'label' ] ) ) { $horizontalGroupData[ 'renderLabels' ] = true; } } else if ( $item[ 'type' ] === 'header' ) { $horizontalGroupData[ 'header' ] = $data[ 'value' ]; } } return $horizontalGroupData; } /** * check if infobox item is a title, title inside the hero module or a label * and if so, remove from it HTML tags. * If label after sanitization is empty- contain only image- do not * sanitize it. * * @param string $type type of infobox item * @param array $data infobox item data * @return array infobox $data with sanitized title param if needed */ public function sanitizeInfoboxFields( $type, $data ) { if ( $type === 'data' ) { $sanitizedLabel = $this->sanitizeElementData( $data[ 'label' ], '' ); if ( !empty( $sanitizedLabel) ) { $data[ 'label' ] = $sanitizedLabel; } } else if ( $type === 'horizontal-group-content' ) { foreach ( $data[ 'labels' ] as $key => $label ) { $sanitizedLabel = $this->sanitizeElementData( $label, '' ); if ( !empty( $sanitizedLabel ) ) { $data[ 'labels' ][ $key ] = $sanitizedLabel; } } } else if ( $type === 'title' ) { $data[ 'value' ] = $this->sanitizeElementData( $data[ 'value' ] ); } else if ( $type === 'hero-mobile' && !empty( $data[ 'title' ][ 'value' ] ) ) { $data[ 'title' ][ 'value' ] = $this->sanitizeElementData( $data[ 'title' ][ 'value' ] ); } return $data; } /** * process single title or label * * @param $elementText * @param string $allowedTags * @return string */ private function sanitizeElementData( $elementText, $allowedTags = null ) { $elementTextAfterTrim = trim( strip_tags( $elementText, $allowedTags ) ); if ( $elementTextAfterTrim !== $elementText ) { WikiaLogger::instance()->info( 'Striping HTML tags from infobox element' ); $elementText = $elementTextAfterTrim; } return $elementText; } /** * extends image data * * @param array $data * * @return bool|array */ public function extendImageData( $data ) { $thumbnail = $this->getThumbnail( $data[ 'name' ] ); $ref = null; if ( !$thumbnail ) { return false; } wfRunHooks( 'PortableInfoboxRenderServiceHelper::extendImageData', [ $data, &$ref ] ); $data[ 'ref' ] = $ref; $data[ 'height' ] = $thumbnail->getHeight(); $data[ 'width' ] = $thumbnail->getWidth(); $data[ 'thumbnail' ] = $this->getPhysicalSizeThumbUrl( $thumbnail ); $data[ 'key' ] = urlencode( $data[ 'key' ] ); $data[ 'media-type' ] = $data[ 'isVideo' ] ? 'video' : 'image'; return $data; } /** * checks if infobox data item is valid hero component data. * If image is smaller than MINIMAL_HERO_IMG_WIDTH const, doesn't render the hero module. * * @param array $item - infobox data item * @param array $heroData - hero component data * * @return bool */ public function isValidHeroDataItem( $item, $heroData ) { $type = $item[ 'type' ]; if ( $type === 'title' && !array_key_exists( 'title', $heroData ) ) { return true; } if ( $type === 'image' && !array_key_exists( 'image', $heroData ) && count( $item[ 'data' ] ) === 1 ) { $imageWidth = $this->getFileWidth( $item[ 'data' ][ 0 ][ 'name' ] ); if ( $imageWidth >= self::MINIMAL_HERO_IMG_WIDTH ) { return true; } } return false; } /** * required for testing mobile template rendering * @return bool */ public function isWikiaMobile() { return \F::app()->checkSkin( 'wikiamobile' ); } /** * check if item type is supported and logs unsupported types * * @param string $type - template type * @param array $templates - array of supported templates * * @return bool */ public function isTypeSupportedInTemplates( $type, $templates ) { $isValid = true; if ( !isset( $templates[ $type ] ) ) { WikiaLogger::instance()->info( self::LOGGER_LABEL, [ 'type' => $type ] ); $isValid = false; } return $isValid; } /** * return real width of the image. * @param Title $title * @return int number */ private function getFileWidth( $title ) { $file = \WikiaFileHelper::getFileFromTitle( $title ); if ( $file ) { return $file->getWidth(); } } /** * @desc create a thumb of the image from file title. * @param Title $title * @return bool|MediaTransformOutput */ private function getThumbnail( $title ) { $file = \WikiaFileHelper::getFileFromTitle( $title ); if ( $file ) { $size = $this->getAdjustedImageSize( $file ); $thumb = $file->transform( $size ); if ( !is_null( $thumb ) && !$thumb->isError() ) { return $thumb; } } return false; } /** * @desc return physicalsize thumbnail URL * @todo Special case for starwars.wikia.com, * @todo rethink approach to images as a part of https://wikia-inc.atlassian.net/browse/DAT-3075 * @param $thumbnail \MediaTransformOutput * @return string thumbnail URL */ private function getPhysicalSizeThumbUrl( $thumbnail ) { global $wgPortableInfoboxCustomImageWidth; if ( !empty( $wgPortableInfoboxCustomImageWidth ) ) { $file = $thumbnail->file; $height = min( self::MAX_DESKTOP_THUMBNAIL_HEIGHT, $file->getHeight() ); return $file->createThumb( $wgPortableInfoboxCustomImageWidth, $height ); } else { return $thumbnail->getUrl(); } } /** * @desc get image size according to the width and height limitations: * Height on desktop cannot be bigger than 500px * Width have to be adjusted to const for mobile or desktop infobox * @param $image * @return array width and height */ public function getAdjustedImageSize( $image ) { if ( $this->isWikiaMobile() ) { $width = self::MOBILE_THUMBNAIL_WIDTH; $height = null; } else { $height = min( self::MAX_DESKTOP_THUMBNAIL_HEIGHT, $image->getHeight() ); $width = self::DESKTOP_THUMBNAIL_WIDTH; } return [ 'height' => $height, 'width' => $width ]; } }