2015-07-28 11:49:17 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Wikia\PortableInfobox\Helpers;
|
|
|
|
|
|
|
|
use \Wikia\Logger\WikiaLogger;
|
|
|
|
|
|
|
|
class PortableInfoboxRenderServiceHelper {
|
|
|
|
const LOGGER_LABEL = 'portable-infobox-render-not-supported-type';
|
2015-07-29 11:51:55 +00:00
|
|
|
//todo: https://wikia-inc.atlassian.net/browse/DAT-3075
|
|
|
|
//todo: figure out what to do when user changes default infobox width via custom theming
|
2015-07-28 11:49:17 +00:00
|
|
|
const DESKTOP_THUMBNAIL_WIDTH = 270;
|
|
|
|
const MOBILE_THUMBNAIL_WIDTH = 360;
|
|
|
|
const MINIMAL_HERO_IMG_WIDTH = 300;
|
2015-09-09 08:16:00 +00:00
|
|
|
const MAX_DESKTOP_THUMBNAIL_HEIGHT = 500;
|
2015-07-28 11:49:17 +00:00
|
|
|
|
2015-09-09 11:49:16 +00:00
|
|
|
function __construct() {}
|
2015-07-28 11:49:17 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* creates special data structure for horizontal group from group data
|
|
|
|
*
|
|
|
|
* @param array $groupData
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function createHorizontalGroupData( $groupData ) {
|
2015-09-08 14:29:41 +00:00
|
|
|
$horizontalGroupData = [
|
2015-07-28 11:49:17 +00:00
|
|
|
'labels' => [],
|
2015-09-07 11:17:03 +00:00
|
|
|
'values' => [],
|
|
|
|
'renderLabels' => false
|
2015-07-28 11:49:17 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
foreach ( $groupData as $item ) {
|
2015-09-09 08:01:24 +00:00
|
|
|
$data = $item[ 'data' ];
|
2015-07-28 11:49:17 +00:00
|
|
|
|
2015-09-09 08:01:24 +00:00
|
|
|
if ( $item[ 'type' ] === 'data' ) {
|
|
|
|
array_push( $horizontalGroupData[ 'labels' ], $data[ 'label' ] );
|
|
|
|
array_push( $horizontalGroupData[ 'values' ], $data[ 'value' ] );
|
2015-09-07 11:17:03 +00:00
|
|
|
|
2015-09-09 08:01:24 +00:00
|
|
|
if ( !empty( $data[ 'label' ] ) ) {
|
|
|
|
$horizontalGroupData[ 'renderLabels' ] = true;
|
2015-09-08 14:29:41 +00:00
|
|
|
}
|
2015-09-09 14:00:19 +00:00
|
|
|
} else if ( $item[ 'type' ] === 'header' ) {
|
2015-09-09 14:00:59 +00:00
|
|
|
$horizontalGroupData[ 'header' ] = $data[ 'value' ];
|
2015-07-28 11:49:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $horizontalGroupData;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-11-03 13:45:27 +00:00
|
|
|
* check if infobox item is a title, title inside the hero module or a label
|
2015-11-05 13:21:20 +00:00
|
|
|
* and if so, remove from it HTML tags.
|
|
|
|
* If label after sanitization is empty- contain only image- do not
|
|
|
|
* sanitize it.
|
2015-07-28 11:49:17 +00:00
|
|
|
*
|
|
|
|
* @param string $type type of infobox item
|
|
|
|
* @param array $data infobox item data
|
|
|
|
* @return array infobox $data with sanitized title param if needed
|
|
|
|
*/
|
2015-11-05 13:21:20 +00:00
|
|
|
public function sanitizeInfoboxFields( $type, $data ) {
|
|
|
|
if ( $type === 'data' ) {
|
|
|
|
$sanitizedLabel = $this->sanitizeElementData( $data[ 'label' ], '<a>' );
|
|
|
|
|
|
|
|
if ( !empty( $sanitizedLabel) ) {
|
|
|
|
$data[ 'label' ] = $sanitizedLabel;
|
|
|
|
}
|
2015-11-05 17:57:53 +00:00
|
|
|
} else if ( $type === 'horizontal-group-content' ) {
|
|
|
|
foreach ( $data[ 'labels' ] as $key => $label ) {
|
|
|
|
$sanitizedLabel = $this->sanitizeElementData( $label, '<a>' );
|
|
|
|
if ( !empty( $sanitizedLabel ) ) {
|
|
|
|
$data[ 'labels' ][ $key ] = $sanitizedLabel;
|
|
|
|
}
|
|
|
|
}
|
2015-11-05 13:21:20 +00:00
|
|
|
} else if ( $type === 'title' ) {
|
2015-11-03 13:45:27 +00:00
|
|
|
$data[ 'value' ] = $this->sanitizeElementData( $data[ 'value' ] );
|
2015-11-05 13:21:20 +00:00
|
|
|
} else if ( $type === 'hero-mobile' && !empty( $data[ 'title' ][ 'value' ] ) ) {
|
2015-11-03 13:45:27 +00:00
|
|
|
$data[ 'title' ][ 'value' ] = $this->sanitizeElementData( $data[ 'title' ][ 'value' ] );
|
2015-07-28 11:49:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
2015-11-03 13:45:27 +00:00
|
|
|
/**
|
|
|
|
* process single title or label
|
|
|
|
*
|
2015-11-03 16:19:29 +00:00
|
|
|
* @param $elementText
|
2015-11-03 15:58:25 +00:00
|
|
|
* @param string $allowedTags
|
2015-11-03 13:45:27 +00:00
|
|
|
* @return string
|
|
|
|
*/
|
2015-11-03 16:19:29 +00:00
|
|
|
private function sanitizeElementData( $elementText, $allowedTags = null ) {
|
2015-11-05 13:21:20 +00:00
|
|
|
$elementTextAfterTrim = trim( strip_tags( $elementText, $allowedTags ) );
|
2015-11-03 15:58:25 +00:00
|
|
|
|
2015-11-05 13:21:20 +00:00
|
|
|
if ( $elementTextAfterTrim !== $elementText ) {
|
|
|
|
WikiaLogger::instance()->info( 'Striping HTML tags from infobox element' );
|
|
|
|
$elementText = $elementTextAfterTrim;
|
2015-11-03 13:45:27 +00:00
|
|
|
}
|
2015-11-03 16:19:29 +00:00
|
|
|
return $elementText;
|
2015-11-03 13:45:27 +00:00
|
|
|
}
|
|
|
|
|
2015-07-28 11:49:17 +00:00
|
|
|
/**
|
|
|
|
* extends image data
|
|
|
|
*
|
|
|
|
* @param array $data
|
|
|
|
*
|
|
|
|
* @return bool|array
|
|
|
|
*/
|
|
|
|
public function extendImageData( $data ) {
|
2015-09-09 08:01:24 +00:00
|
|
|
$thumbnail = $this->getThumbnail( $data[ 'name' ] );
|
2015-09-28 15:46:40 +00:00
|
|
|
$ref = null;
|
2015-07-28 11:49:17 +00:00
|
|
|
|
2015-09-08 14:29:41 +00:00
|
|
|
if ( !$thumbnail ) {
|
2015-07-28 11:49:17 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-09-30 08:10:31 +00:00
|
|
|
wfRunHooks( 'PortableInfoboxRenderServiceHelper::extendImageData', [ $data, &$ref ] );
|
2015-12-11 10:56:41 +00:00
|
|
|
$dimensions = self::getImageSizesToDisplay( $thumbnail );
|
2015-09-28 15:46:40 +00:00
|
|
|
|
|
|
|
$data[ 'ref' ] = $ref;
|
2015-12-11 10:56:41 +00:00
|
|
|
$data[ 'height' ] = $dimensions[ 'height' ];
|
|
|
|
$data[ 'width' ] = $dimensions[ 'width' ];
|
|
|
|
$data[ 'thumbnail' ] = $thumbnail->getUrl();
|
2015-09-09 08:01:24 +00:00
|
|
|
$data[ 'key' ] = urlencode( $data[ 'key' ] );
|
|
|
|
$data[ 'media-type' ] = $data[ 'isVideo' ] ? 'video' : 'image';
|
2015-07-28 11:49:17 +00:00
|
|
|
|
|
|
|
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 ) {
|
2015-09-09 08:01:24 +00:00
|
|
|
$type = $item[ 'type' ];
|
2015-07-28 11:49:17 +00:00
|
|
|
|
|
|
|
if ( $type === 'title' && !array_key_exists( 'title', $heroData ) ) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-10-16 01:15:52 +00:00
|
|
|
if ( $type === 'image' && !array_key_exists( 'image', $heroData ) && count( $item[ 'data' ] ) === 1 ) {
|
|
|
|
$imageWidth = $this->getFileWidth( $item[ 'data' ][ 0 ][ 'name' ] );
|
2015-07-28 11:49:17 +00:00
|
|
|
|
2015-07-28 14:13:36 +00:00
|
|
|
if ( $imageWidth >= self::MINIMAL_HERO_IMG_WIDTH ) {
|
2015-07-28 11:49:17 +00:00
|
|
|
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
|
|
|
|
*/
|
2015-07-29 11:51:55 +00:00
|
|
|
public function isTypeSupportedInTemplates( $type, $templates ) {
|
2015-07-28 11:49:17 +00:00
|
|
|
$isValid = true;
|
|
|
|
|
2015-09-09 08:01:24 +00:00
|
|
|
if ( !isset( $templates[ $type ] ) ) {
|
2015-07-28 11:49:17 +00:00
|
|
|
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 );
|
|
|
|
|
2015-09-09 08:01:24 +00:00
|
|
|
if ( $file ) {
|
2015-07-28 11:49:17 +00:00
|
|
|
return $file->getWidth();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-09-08 14:29:41 +00:00
|
|
|
* @desc create a thumb of the image from file title.
|
2015-07-28 11:49:17 +00:00
|
|
|
* @param Title $title
|
|
|
|
* @return bool|MediaTransformOutput
|
|
|
|
*/
|
|
|
|
private function getThumbnail( $title ) {
|
|
|
|
$file = \WikiaFileHelper::getFileFromTitle( $title );
|
|
|
|
|
|
|
|
if ( $file ) {
|
2015-12-11 11:02:00 +00:00
|
|
|
$size = $this->getImageSizesForThumbnailer( $file );
|
2015-09-09 08:16:00 +00:00
|
|
|
$thumb = $file->transform( $size );
|
2015-09-08 14:29:41 +00:00
|
|
|
|
|
|
|
if ( !is_null( $thumb ) && !$thumb->isError() ) {
|
2015-07-28 11:49:17 +00:00
|
|
|
return $thumb;
|
|
|
|
}
|
|
|
|
}
|
2015-09-09 08:01:24 +00:00
|
|
|
|
2015-07-28 11:49:17 +00:00
|
|
|
return false;
|
|
|
|
}
|
2015-09-09 08:16:00 +00:00
|
|
|
|
2015-12-11 00:41:07 +00:00
|
|
|
/**
|
2015-12-11 10:56:41 +00:00
|
|
|
* @desc get image size to be passed to a thumbnailer.
|
|
|
|
*
|
|
|
|
* Return size according to the width and height limitations:
|
2015-09-09 08:16:00 +00:00
|
|
|
* Height on desktop cannot be bigger than 500px
|
|
|
|
* Width have to be adjusted to const for mobile or desktop infobox
|
2015-12-11 10:56:41 +00:00
|
|
|
* if $wgPortableInfoboxCustomImageWidth is set, do not change max height
|
|
|
|
* and set width to $wgPortableInfoboxCustomImageWidth.
|
2015-09-09 08:16:00 +00:00
|
|
|
* @param $image
|
|
|
|
* @return array width and height
|
|
|
|
*/
|
2015-12-11 11:02:00 +00:00
|
|
|
public function getImageSizesForThumbnailer( $image ) {
|
2015-12-11 10:56:41 +00:00
|
|
|
global $wgPortableInfoboxCustomImageWidth;
|
|
|
|
|
2015-09-09 08:16:00 +00:00
|
|
|
if ( $this->isWikiaMobile() ) {
|
|
|
|
$width = self::MOBILE_THUMBNAIL_WIDTH;
|
|
|
|
$height = null;
|
2015-12-11 10:56:41 +00:00
|
|
|
} else if ( empty( $wgPortableInfoboxCustomImageWidth ) ) {
|
2015-09-09 08:16:00 +00:00
|
|
|
$height = min( self::MAX_DESKTOP_THUMBNAIL_HEIGHT, $image->getHeight() );
|
|
|
|
$width = self::DESKTOP_THUMBNAIL_WIDTH;
|
2015-12-11 10:56:41 +00:00
|
|
|
} else {
|
|
|
|
$height = $image->getHeight();
|
|
|
|
$width = $wgPortableInfoboxCustomImageWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
return [ 'height' => $height, 'width' => $width ];
|
|
|
|
}
|
|
|
|
|
2015-12-11 11:06:44 +00:00
|
|
|
/**
|
|
|
|
* @desc if it's not a request from mobile skin and wgPortableInfoboxCustomImageWidth
|
|
|
|
* is set, the $thumbnail->getWidth() can return some big value - we need
|
|
|
|
* to adjust it to DESKTOP_THUMBNAIL_WIDTH to look good in the infobox.
|
|
|
|
* Also, the $height have to be adjusted here to make image look good in infobox.
|
|
|
|
* @param $thumbnail
|
|
|
|
* @return array width and height which will be displayed i.e. in the width
|
|
|
|
* and height properties of the img tag
|
|
|
|
*/
|
2015-12-11 17:56:49 +00:00
|
|
|
public function getImageSizesToDisplay( $thumbnail ) {
|
2015-12-11 10:56:41 +00:00
|
|
|
global $wgPortableInfoboxCustomImageWidth;
|
|
|
|
|
|
|
|
if ( !$this->isWikiaMobile() && !empty( $wgPortableInfoboxCustomImageWidth ) ) {
|
|
|
|
$width = min( self::DESKTOP_THUMBNAIL_WIDTH, $thumbnail->getWidth() );
|
|
|
|
$height = min( self::MAX_DESKTOP_THUMBNAIL_HEIGHT, $width * $thumbnail->getHeight() / $thumbnail->getWidth());
|
|
|
|
} else {
|
|
|
|
$width = $thumbnail->getWidth();
|
|
|
|
$height = $thumbnail->getHeight();
|
2015-09-09 08:16:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return [ 'height' => $height, 'width' => $width ];
|
|
|
|
}
|
2015-09-09 08:01:24 +00:00
|
|
|
}
|