PortableInfobox/services/PortableInfoboxRenderService.class.php

278 lines
6.9 KiB
PHP
Raw Normal View History

<?php
2016-12-29 10:58:27 +00:00
use Wikia\PortableInfobox\Helpers\PortableInfoboxImagesHelper;
2017-01-10 14:24:39 +00:00
use Wikia\PortableInfobox\Helpers\PortableInfoboxMustacheEngine;
2015-07-02 11:55:39 +00:00
class PortableInfoboxRenderService extends WikiaService {
2016-12-29 10:28:26 +00:00
const DEFAULT_DESKTOP_THUMBNAIL_WIDTH = 270;
const EUROPA_THUMBNAIL_WIDTH = 300;
protected $templateEngine;
2016-12-29 10:28:26 +00:00
protected $imagesWidth = self::DEFAULT_DESKTOP_THUMBNAIL_WIDTH;
2016-12-28 12:10:57 +00:00
protected $inlineStyles;
2016-12-29 10:28:26 +00:00
private $helper;
2015-07-02 11:55:39 +00:00
function __construct() {
parent::__construct();
$this->templateEngine = new PortableInfoboxMustacheEngine();
}
/**
* renders infobox
*
* @param array $infoboxdata
2015-07-02 11:55:39 +00:00
*
* @param $theme
* @param $layout
2016-12-28 12:10:57 +00:00
* @param $accentColor
* @param $accentColorText
* @return string - infobox HTML
*/
2016-12-28 12:10:57 +00:00
public function renderInfobox( array $infoboxdata, $theme, $layout, $accentColor, $accentColorText ) {
$this->inlineStyles = $this->getInlineStyles( $accentColor, $accentColorText );
// decide on image width, if europa go with bigger images! else default size
2016-12-29 10:58:27 +00:00
$this->imagesWidth = $this->isEuropaTheme() ? self::EUROPA_THUMBNAIL_WIDTH :
2016-12-29 10:28:26 +00:00
self::DEFAULT_DESKTOP_THUMBNAIL_WIDTH;
2016-12-28 12:10:57 +00:00
2016-12-29 10:28:26 +00:00
$infoboxHtmlContent = $this->renderChildren( $infoboxdata );
2015-07-02 11:55:39 +00:00
if ( !empty( $infoboxHtmlContent ) ) {
$output = $this->renderItem( 'wrapper', [
'content' => $infoboxHtmlContent,
'theme' => $theme,
'layout' => $layout,
2016-12-29 10:58:27 +00:00
'isEuropaEnabled' => $this->isEuropaTheme()
] );
} else {
$output = '';
}
return $output;
}
2016-12-29 13:17:48 +00:00
protected function getImageHelper() {
2016-12-29 10:28:26 +00:00
if ( !isset( $this->helper ) ) {
2016-12-29 10:58:27 +00:00
$this->helper = new PortableInfoboxImagesHelper();
2016-12-29 10:28:26 +00:00
}
return $this->helper;
}
/**
* Produces HTML output for item type and data
*
* @param $type
* @param array $data
* @return string
*/
protected function render( $type, array $data ) {
return $this->templateEngine->render( $type, $data );
}
/**
* renders part of infobox
*
* @param string $type
* @param array $data
*
* @return string - HTML
*/
protected function renderItem( $type, array $data ) {
2016-12-29 10:28:26 +00:00
switch ( $type ) {
case 'group':
$result = $this->renderGroup( $data );
break;
case 'header':
$result = $this->renderHeader( $data );
break;
case 'image':
$result = $this->renderImage( $data );
break;
case 'title':
$result = $this->renderTitle( $data );
break;
default:
$result = $this->render( $type, $data );
break;
}
2016-12-29 10:28:26 +00:00
return $result;
}
/**
* renders group infobox component
*
* @param array $groupData
2015-07-02 11:55:39 +00:00
*
* @return string - group HTML markup
*/
protected function renderGroup( $groupData ) {
$cssClasses = [ ];
$groupHTMLContent = '';
2017-01-11 10:27:23 +00:00
$children = $groupData['value'];
2016-12-29 10:28:26 +00:00
$layout = $groupData['layout'];
$collapse = $groupData['collapse'];
2017-01-10 14:24:39 +00:00
$rowItems = $groupData['row-items'];
2017-01-10 14:24:39 +00:00
if ( $rowItems > 0 ) {
$cssClasses[] = 'pi-smart-group';
2017-01-11 10:27:23 +00:00
$items = $this->createSmartGroups( $children, $rowItems );
2017-01-10 14:24:39 +00:00
$groupHTMLContent .= $this->renderChildren( $items );
} elseif ( $layout === 'horizontal' ) {
$groupHTMLContent .= $this->renderItem(
'horizontal-group-content',
2017-01-11 10:27:23 +00:00
$this->createHorizontalGroupData( $children )
);
} else {
2017-01-11 10:27:23 +00:00
$groupHTMLContent .= $this->renderChildren( $children );
}
2017-01-11 10:27:23 +00:00
if ( $collapse !== null && count( $children ) > 0 && $children[0]['type'] === 'header' ) {
$cssClasses[] = 'pi-collapse';
$cssClasses[] = 'pi-collapse-' . $collapse;
}
return $this->render( 'group', [
'content' => $groupHTMLContent,
'cssClasses' => implode( ' ', $cssClasses )
] );
}
/**
* If image element has invalid thumbnail, doesn't render this element at all.
2015-07-02 11:55:39 +00:00
*
* @param $data
* @return string
*/
protected function renderImage( $data ) {
2016-12-29 13:17:48 +00:00
$helper = $this->getImageHelper();
$images = [ ];
for ( $i = 0; $i < count( $data ); $i++ ) {
2016-12-29 10:28:26 +00:00
$data[$i] = $helper->extendImageData( $data[$i], $this->imagesWidth );
2016-12-29 10:28:26 +00:00
if ( !!$data[$i] ) {
$images[] = $data[$i];
}
}
2015-07-02 11:55:39 +00:00
if ( count( $images ) === 0 ) {
return '';
}
if ( count( $images ) === 1 ) {
2016-12-29 10:28:26 +00:00
$data = $images[0];
$templateName = 'image';
} else {
// More than one image means image collection
$data = $helper->extendImageCollectionData( $images );
$templateName = 'image-collection';
}
return $this->render( $templateName, $data );
}
2016-12-28 12:10:57 +00:00
2016-12-29 10:28:26 +00:00
protected function renderTitle( $data ) {
$data['inlineStyles'] = $this->inlineStyles;
return $this->render( 'title', $data );
}
protected function renderHeader( $data ) {
$data['inlineStyles'] = $this->inlineStyles;
return $this->render( 'header', $data );
}
protected function renderChildren( $children ) {
$result = '';
foreach ( $children as $child ) {
$type = $child['type'];
if ( $this->templateEngine->isSupportedType( $type ) ) {
$result .= $this->renderItem( $type, $child['data'] );
}
}
return $result;
}
2016-12-28 12:10:57 +00:00
private function getInlineStyles( $accentColor, $accentColorText ) {
$backgroundColor = empty( $accentColor ) ? '' : "background-color:{$accentColor};";
$color = empty( $accentColorText ) ? '' : "color:{$accentColorText};";
2016-12-28 12:36:57 +00:00
return "{$backgroundColor}{$color}";
2016-12-28 12:10:57 +00:00
}
2016-12-29 10:28:26 +00:00
private function createHorizontalGroupData( $groupData ) {
$horizontalGroupData = [
'labels' => [ ],
'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;
}
} elseif ( $item['type'] === 'header' ) {
$horizontalGroupData['header'] = $data['value'];
}
}
return $horizontalGroupData;
}
2016-12-29 10:58:27 +00:00
private function isEuropaTheme() {
global $wgEnablePortableInfoboxEuropaTheme;
return !empty( $wgEnablePortableInfoboxEuropaTheme );
}
2017-01-10 14:24:39 +00:00
private function createSmartGroups( $groupData, $rowCapacity ) {
$result = [ ];
2017-01-11 10:27:23 +00:00
$rowSpan = 0;
$rowItems = [ ];
2017-01-10 14:24:39 +00:00
foreach ( $groupData as $item ) {
$data = $item['data'];
if ( $item['type'] === 'data' && ( !isset( $data['layout'] ) || $data['layout'] !== 'default' ) ) {
2017-01-11 10:27:23 +00:00
if ( $rowSpan + $data['span'] > $rowCapacity ) {
$result = array_merge( $result, $this->applyRowItemsStyles( $rowItems, $rowSpan ) );
$rowSpan = 0;
$rowItems = [ ];
2017-01-10 14:24:39 +00:00
}
2017-01-11 10:27:23 +00:00
$rowSpan += $data['span'];
$rowItems[] = $item;
2017-01-10 14:24:39 +00:00
} else {
// smart wrapping works only for data tags
2017-01-11 10:27:23 +00:00
if ( !empty( $rowItems ) ) {
$result = array_merge( $result, $this->applyRowItemsStyles( $rowItems, $rowSpan ) );
$rowSpan = 0;
$rowItems = [ ];
2017-01-10 14:24:39 +00:00
}
$result[] = $item;
}
}
2017-01-11 10:27:23 +00:00
return array_merge( $result, $this->applyRowItemsStyles( $rowItems, $rowSpan ) );
2017-01-10 14:24:39 +00:00
}
2017-01-11 10:27:23 +00:00
private function applyRowItemsStyles( $rowItems, $capacity ) {
2017-01-10 14:24:39 +00:00
return array_map( function ( $item ) use ( $capacity ) {
$width = round( ( $item['data']['span'] / $capacity ) * 100 );
$item['data']['cssClasses'] = 'pi-smart-data';
$item['data']['inlineStyles'] = "width: {$width}%;";
return $item;
2017-01-11 10:27:23 +00:00
}, $rowItems );
2017-01-10 14:24:39 +00:00
}
}