2015-04-27 14:05:31 +00:00
|
|
|
<?php
|
|
|
|
|
2018-08-09 09:49:10 +00:00
|
|
|
use PortableInfobox\Helpers\PortableInfoboxTemplateEngine;
|
2015-07-28 11:49:17 +00:00
|
|
|
|
2017-07-07 13:12:32 +00:00
|
|
|
class PortableInfoboxRenderService {
|
2018-08-09 09:49:10 +00:00
|
|
|
// keep synced with css variables (--pi-width)
|
2017-01-13 12:57:17 +00:00
|
|
|
const DEFAULT_DESKTOP_INFOBOX_WIDTH = 270;
|
2017-01-10 12:20:13 +00:00
|
|
|
const DEFAULT_DESKTOP_THUMBNAIL_WIDTH = 350;
|
2016-12-29 10:28:26 +00:00
|
|
|
|
2016-12-27 14:34:21 +00:00
|
|
|
protected $templateEngine;
|
2016-12-28 12:10:57 +00:00
|
|
|
protected $inlineStyles;
|
2015-04-27 14:05:31 +00:00
|
|
|
|
2017-07-07 13:12:32 +00:00
|
|
|
public function __construct() {
|
2018-08-08 09:31:33 +00:00
|
|
|
$this->templateEngine = new PortableInfoboxTemplateEngine();
|
2015-04-27 14:05:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* renders infobox
|
|
|
|
*
|
|
|
|
* @param array $infoboxdata
|
2015-07-02 11:55:39 +00:00
|
|
|
*
|
2018-08-16 09:25:53 +00:00
|
|
|
* @param string $theme
|
|
|
|
* @param string $layout
|
|
|
|
* @param string $accentColor
|
|
|
|
* @param string $accentColorText
|
2015-04-27 14:05:31 +00:00
|
|
|
* @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 );
|
2015-04-27 14:05:31 +00:00
|
|
|
|
2016-12-29 10:28:26 +00:00
|
|
|
$infoboxHtmlContent = $this->renderChildren( $infoboxdata );
|
2015-04-27 14:05:31 +00:00
|
|
|
|
2015-07-02 11:55:39 +00:00
|
|
|
if ( !empty( $infoboxHtmlContent ) ) {
|
2016-03-29 10:31:03 +00:00
|
|
|
$output = $this->renderItem( 'wrapper', [
|
2016-03-29 10:12:11 +00:00
|
|
|
'content' => $infoboxHtmlContent,
|
|
|
|
'theme' => $theme,
|
2018-07-25 15:01:45 +00:00
|
|
|
'layout' => $layout
|
2016-03-29 10:31:03 +00:00
|
|
|
] );
|
2015-04-27 14:05:31 +00:00
|
|
|
} else {
|
|
|
|
$output = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
}
|
|
|
|
|
2016-12-27 14:09:55 +00:00
|
|
|
/**
|
|
|
|
* Produces HTML output for item type and data
|
|
|
|
*
|
2018-08-16 09:25:53 +00:00
|
|
|
* @param string $type
|
2016-12-27 14:09:55 +00:00
|
|
|
* @param array $data
|
|
|
|
* @return string
|
|
|
|
*/
|
2016-12-27 14:34:21 +00:00
|
|
|
protected function render( $type, array $data ) {
|
2016-12-27 14:58:01 +00:00
|
|
|
return $this->templateEngine->render( $type, $data );
|
2016-12-27 14:09:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* renders part of infobox
|
|
|
|
*
|
|
|
|
* @param string $type
|
|
|
|
* @param array $data
|
|
|
|
*
|
2016-12-27 14:34:21 +00:00
|
|
|
* @return string - HTML
|
2016-12-27 14:09:55 +00:00
|
|
|
*/
|
2016-12-27 14:34:21 +00:00
|
|
|
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;
|
2018-08-12 09:45:29 +00:00
|
|
|
case 'media':
|
|
|
|
$result = $this->renderMedia( $data );
|
2016-12-29 10:28:26 +00:00
|
|
|
break;
|
|
|
|
case 'title':
|
|
|
|
$result = $this->renderTitle( $data );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
$result = $this->render( $type, $data );
|
|
|
|
break;
|
2016-12-27 14:09:55 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 10:28:26 +00:00
|
|
|
return $result;
|
2016-12-27 14:09:55 +00:00
|
|
|
}
|
|
|
|
|
2015-04-27 14:05:31 +00:00
|
|
|
/**
|
|
|
|
* renders group infobox component
|
|
|
|
*
|
|
|
|
* @param array $groupData
|
2015-07-02 11:55:39 +00:00
|
|
|
*
|
2015-04-27 14:05:31 +00:00
|
|
|
* @return string - group HTML markup
|
|
|
|
*/
|
2016-12-27 14:34:21 +00:00
|
|
|
protected function renderGroup( $groupData ) {
|
2018-08-12 09:45:29 +00:00
|
|
|
$cssClasses = [];
|
2015-04-27 14:05:31 +00:00
|
|
|
$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'];
|
2015-04-27 14:05:31 +00:00
|
|
|
|
2017-01-10 14:24:39 +00:00
|
|
|
if ( $rowItems > 0 ) {
|
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' ) {
|
2015-07-28 09:46:41 +00:00
|
|
|
$groupHTMLContent .= $this->renderItem(
|
|
|
|
'horizontal-group-content',
|
2017-01-11 10:27:23 +00:00
|
|
|
$this->createHorizontalGroupData( $children )
|
2015-07-28 09:46:41 +00:00
|
|
|
);
|
|
|
|
} else {
|
2017-01-11 10:27:23 +00:00
|
|
|
$groupHTMLContent .= $this->renderChildren( $children );
|
2015-04-27 14:05:31 +00:00
|
|
|
}
|
|
|
|
|
2017-01-11 10:27:23 +00:00
|
|
|
if ( $collapse !== null && count( $children ) > 0 && $children[0]['type'] === 'header' ) {
|
2015-10-26 21:59:34 +00:00
|
|
|
$cssClasses[] = 'pi-collapse';
|
|
|
|
$cssClasses[] = 'pi-collapse-' . $collapse;
|
|
|
|
}
|
|
|
|
|
2016-12-27 14:09:55 +00:00
|
|
|
return $this->render( 'group', [
|
2015-10-26 21:59:34 +00:00
|
|
|
'content' => $groupHTMLContent,
|
2016-03-17 09:37:18 +00:00
|
|
|
'cssClasses' => implode( ' ', $cssClasses )
|
2015-10-26 21:59:34 +00:00
|
|
|
] );
|
2015-04-27 14:05:31 +00:00
|
|
|
}
|
|
|
|
|
2015-07-01 13:18:20 +00:00
|
|
|
/**
|
2016-12-27 14:09:55 +00:00
|
|
|
* If image element has invalid thumbnail, doesn't render this element at all.
|
2015-07-02 11:55:39 +00:00
|
|
|
*
|
2018-08-16 09:25:53 +00:00
|
|
|
* @param array $data
|
2015-07-01 13:18:20 +00:00
|
|
|
* @return string
|
|
|
|
*/
|
2018-08-12 09:45:29 +00:00
|
|
|
protected function renderMedia( $data ) {
|
2018-08-22 14:20:49 +00:00
|
|
|
if ( count( $data ) === 0 || !$data[0] ) {
|
2016-12-27 14:09:55 +00:00
|
|
|
return '';
|
2015-07-21 23:13:28 +00:00
|
|
|
}
|
2015-07-20 13:00:35 +00:00
|
|
|
|
2018-08-22 14:20:49 +00:00
|
|
|
if ( count( $data ) === 1 ) {
|
|
|
|
$data = $data[0];
|
2018-08-12 09:45:29 +00:00
|
|
|
$templateName = 'media';
|
2016-12-27 14:09:55 +00:00
|
|
|
} else {
|
|
|
|
// More than one image means image collection
|
2018-08-22 14:20:49 +00:00
|
|
|
$data = [ 'images' => $data ];
|
2018-08-12 09:45:29 +00:00
|
|
|
$templateName = 'media-collection';
|
2015-07-21 23:13:28 +00:00
|
|
|
}
|
2015-07-20 13:00:35 +00:00
|
|
|
|
2016-12-27 14:09:55 +00:00
|
|
|
return $this->render( $templateName, $data );
|
2015-07-20 13:00:35 +00:00
|
|
|
}
|
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 = [
|
2018-08-12 09:45:29 +00:00
|
|
|
'labels' => [],
|
|
|
|
'values' => [],
|
2016-12-29 10:28:26 +00:00
|
|
|
'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'];
|
2018-08-09 09:41:31 +00:00
|
|
|
$horizontalGroupData['inlineStyles'] = $this->inlineStyles;
|
2016-12-29 10:28:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $horizontalGroupData;
|
|
|
|
}
|
2016-12-29 10:58:27 +00:00
|
|
|
|
2017-01-10 14:24:39 +00:00
|
|
|
private function createSmartGroups( $groupData, $rowCapacity ) {
|
2018-08-12 09:45:29 +00:00
|
|
|
$result = [];
|
2017-01-11 10:27:23 +00:00
|
|
|
$rowSpan = 0;
|
2018-08-12 09:45:29 +00:00
|
|
|
$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-12 13:11:46 +00:00
|
|
|
if ( !empty( $rowItems ) && $rowSpan + $data['span'] > $rowCapacity ) {
|
2017-01-12 11:40:56 +00:00
|
|
|
$result[] = $this->createSmartGroupItem( $rowItems, $rowSpan );
|
2017-01-11 10:27:23 +00:00
|
|
|
$rowSpan = 0;
|
2018-08-12 09:45:29 +00:00
|
|
|
$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 ) ) {
|
2017-01-12 11:40:56 +00:00
|
|
|
$result[] = $this->createSmartGroupItem( $rowItems, $rowSpan );
|
2017-01-11 10:27:23 +00:00
|
|
|
$rowSpan = 0;
|
2018-08-16 09:25:53 +00:00
|
|
|
$rowItems = [];
|
2017-01-10 14:24:39 +00:00
|
|
|
}
|
|
|
|
$result[] = $item;
|
|
|
|
}
|
|
|
|
}
|
2017-01-12 11:40:56 +00:00
|
|
|
if ( !empty( $rowItems ) ) {
|
|
|
|
$result[] = $this->createSmartGroupItem( $rowItems, $rowSpan );
|
|
|
|
}
|
2017-01-10 14:24:39 +00:00
|
|
|
|
2017-01-12 11:40:56 +00:00
|
|
|
return $result;
|
2017-01-10 14:24:39 +00:00
|
|
|
}
|
|
|
|
|
2017-01-12 11:40:56 +00:00
|
|
|
private function createSmartGroupItem( $rowItems, $rowSpan ) {
|
|
|
|
return [
|
|
|
|
'type' => 'smart-group',
|
2017-01-12 13:11:46 +00:00
|
|
|
'data' => $this->createSmartGroupSections( $rowItems, $rowSpan )
|
2017-01-12 11:40:56 +00:00
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2017-01-12 13:11:46 +00:00
|
|
|
private function createSmartGroupSections( $rowItems, $capacity ) {
|
|
|
|
return array_reduce( $rowItems, function ( $result, $item ) use ( $capacity ) {
|
2018-08-20 10:50:36 +00:00
|
|
|
$width = $item['data']['span'] / $capacity * 100;
|
|
|
|
$styles = "width: {$width}%";
|
2017-01-12 13:11:46 +00:00
|
|
|
|
|
|
|
$label = $item['data']['label'] ?? "";
|
|
|
|
if ( !empty( $label ) ) {
|
|
|
|
$result['renderLabels'] = true;
|
2017-01-11 14:04:09 +00:00
|
|
|
}
|
2017-01-12 13:11:46 +00:00
|
|
|
$result['labels'][] = [ 'value' => $label, 'inlineStyles' => $styles ];
|
|
|
|
$result['values'][] = [ 'value' => $item['data']['value'], 'inlineStyles' => $styles ];
|
2017-01-11 11:48:26 +00:00
|
|
|
|
2017-01-12 13:11:46 +00:00
|
|
|
return $result;
|
2018-08-12 09:45:29 +00:00
|
|
|
}, [ 'labels' => [], 'values' => [], 'renderLabels' => false ] );
|
2017-01-10 14:24:39 +00:00
|
|
|
}
|
2015-04-27 14:05:31 +00:00
|
|
|
}
|