<?php
namespace CONECTO\ProviderBundle\Twig\Extension;
use Pimcore\Config;
use Pimcore\Model\Asset;
use Pimcore\Model\Document;
use Pimcore\Navigation\Container;
use Pimcore\Navigation\Builder;
use Symfony\Component\Intl\Countries;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
final class ConectoExtension extends AbstractExtension
{
/**
* @var Builder
*/
private $navigationHelper;
/**
* @param Builder $navigationHelper
*/
public function __construct(Builder $navigationHelper)
{
$this->navigationHelper = $navigationHelper;
}
/**
* @return \Twig_Function[]
*/
public function getFunctions(): array
{
return [
new TwigFunction('date_string', [$this, 'getDate']),
new TwigFunction('date_in_days', [$this, 'getDateInDays']),
new TwigFunction('conecto_country_list', [$this, 'buildCountryList']),
new TwigFunction('conecto_file_get_contents', [$this, 'fileGetContents']),
new TwigFunction('conecto_build_nav', [$this, 'buildMainNavigation']),
new TwigFunction('conecto_get_editable', [$this, 'getEditable']),
new TwigFunction('conecto_get_parent_editable', [$this, 'getParentEditable']),
new TwigFunction('conecto_get_icons', [$this, 'getIcons']),
new TwigFunction('conecto_get_areabricks', [$this, 'getAreaBricks']),
new TwigFunction('conecto_get_thumbnailconf', [$this, 'getThumbnailConf']),
new TwigFunction('conecto_get_hostname', [$this, 'getHostname']),
new TwigFunction('conecto_video_from_dataobject', [$this, 'videoFromDataobject']),
new TwigFunction('include_svg', [$this, 'includeSvg']),
];
}
/**
* @return string
*/
public function getDate(): string
{
$date = new \DateTimeImmutable();
return $date->format('Y-m-d');
}
/**
* @param int $days
* @return string
*/
public function getDateInDays(int $days = 1): string
{
$date = new \DateTime();
$date->add(new \DateInterval('P'.$days.'D'));
return $date->format('Y-m-d');
}
/**
* @param $locale
* @return mixed
*/
public function buildCountryList($locale)
{
return Countries::getNames($locale);
}
/**
* @param string $path
* @return string
*/
public function fileGetContents(string $path)
{
$fileContent = '';
if(file_exists(PIMCORE_WEB_ROOT . '/' . $path)) {
$fileContent = file_get_contents(PIMCORE_WEB_ROOT . '/' . $path);
}
return $fileContent;
}
/**
* @param Document $activeDocument
* @param Document $navigationRootDocument
* @return Container
*/
public function buildMainNavigation(Document $activeDocument, Document $navigationRootDocument): Container
{
return $this->navigationHelper->getNavigation(
$activeDocument,
$navigationRootDocument,
null,
function (\Pimcore\Navigation\Page\Document $page, $doc) {
if (!$doc instanceof Document) {
return;
}
// Add Document as Custom Setting to access Document Properties in Nav
$page->setCustomSetting("document", $doc);
return $page;
}
);
}
/**
* @param Document $document
* @param string $editableName
* @return mixed
*/
public function getEditable(Document $document, string $editableName)
{
return $document->getEditable($editableName);
}
/**
* @param Document $document
* @param string $editableName
* @return mixed
*/
public function getParentEditable(Document $document, string $editableName)
{
$parent = $document->getParent();
if($parent) {
if( method_exists($parent, 'getEditable') ) {
$parentEditable = $parent->getEditable($editableName);
if((
$parentEditable instanceof \Pimcore\Model\Document\Editable\Image
|| $parentEditable instanceof \Pimcore\Model\Document\Editable\Video
) && $parentEditable->getId() > 0
) {
return $parentEditable;
}
}
return $this->getParentEditable($parent, $editableName);
}
return null;
}
/**
* @return array
*/
public function getIcons(): array
{
return \CONECTO\ProviderBundle\Utility\Icon::getIconData();
}
/**
* Function to automatically get all available area bricks,
* because this is needed in different templates.
* Use "disallowed" parameter to remove specific area bricks
* from the list.
* The sorting of the area bricks can be defined in the
* config php files of the area bricks
*
* @param array $disallowed disallowed areabricks to remove from list
* @param array $additional additional areabricks to add to list
* @return array
*/
public function getAreabricks(array $disallowed = [], array $additional = []): array
{
$areaBricksDirs = [];
$areaBricksDirs[] = __DIR__ . '/../../Document/Areabrick/';
$areaBricksDirs[] = PIMCORE_PROJECT_ROOT . '/src/Document/Areabrick/';
$areaBricks = [];
if(sizeof($areaBricksDirs) > 0) {
foreach($areaBricksDirs as $areaBricksDir) {
if(is_dir($areaBricksDir)) {
$areaBricksFilenames = array_diff(scandir($areaBricksDir), ['.', '..', 'AbstractAreabrick.php']);
// Get sorting from AreaBrick php file
foreach($areaBricksFilenames as $filename) {
$customSorting = 9999;
if(file_exists($areaBricksDir . $filename)) {
$fileContent = @file_get_contents($areaBricksDir . $filename);
if($fileContent) {
$lines = explode(PHP_EOL, $fileContent);
$lines = array_map(function($line) {
return trim($line);
}, $lines);
$sortingCommentStart = '/* custom-sorting:';
foreach ($lines as $index => $line) {
if (strpos($line, $sortingCommentStart) !== false) {
$customSorting = trim(str_replace([$sortingCommentStart, "*/"], '', $line));
break;
}
}
}
}
$areaBricks[] = [
'sorting' => $customSorting,
'name' => strtolower(preg_replace('/([a-zA-Z])(?=[A-Z])/', '$1-', str_replace('.php', '', $filename))),
];
}
}
}
}
if($additional && sizeof($additional)) {
foreach($additional as $areaBrick) {
$areaBricks[] = [
'sorting' => 999999,
'name' => $areaBrick,
];
}
}
uasort($areaBricks, function($a, $b) {
return $a['sorting'] - $b['sorting'];
});
return sizeof($disallowed) > 0 ? array_diff(array_column($areaBricks, 'name'), $disallowed) : array_column($areaBricks, 'name');
}
/**
* Get dynamic thumbnail conf
*
* @param string $name name for thumbnail conf
* @param float $ratio thumbnail ratio - defaults to 3/2
* @param float $cols cols to calculate image width - defaults to 1
* @param int $baseWidth base content width
* @return \Pimcore\Model\Asset\Image\Thumbnail\Config
*/
public function getThumbnailConf(string $name = 'default', float $ratio = 1.5, float $cols = 1, int $baseWidth = 1920): \Pimcore\Model\Asset\Image\Thumbnail\Config
{
// thumbnail conf
$minWidth = 380;
$minHeight = floor($minWidth / $ratio);
$breakpoints = [
[
'minWidth' => 576,
'imgWidth' => 767,
'maxCols' => 2
],
[
'minWidth' => 768,
'imgWidth' => 991,
'maxCols' => 3
],
[
'minWidth' => 992,
'imgWidth' => 1199,
'maxCols' => 4
],
[
'minWidth' => 1200,
'imgWidth' => $baseWidth,
'maxCols' => 6
]
];
$medias = [];
$confName = $name . '_' . str_replace('.', '-', round($ratio, 2)) . '_' . str_replace('.', '-', round($cols, 2));
$conf = new \Pimcore\Model\Asset\Image\Thumbnail\Config();
$conf->setName($confName);
$conf->setFormat('SOURCE');
$conf->setQuality(85);
$conf->setHighResolution(1);
$conf->setPreserveColor(false);
$conf->setPreserveMetaData(false);
$conf->setRasterizeSVG(false);
$conf->setDownloadable(false);
// Default size (smartphones)
$conf->addItem('cover', [
"width" => $minWidth,
"height" => $minHeight,
"positioning" => "center",
"forceResize" => true
]);
// add Media queries
for($i = 0; $i < sizeof($breakpoints); $i++) {
$maxThumbWidth = $breakpoints[$i]['imgWidth'];
$tmpCols = $cols > $breakpoints[$i]['maxCols'] ? $breakpoints[$i]['maxCols'] : $cols;
$thumbWidth = floor($maxThumbWidth / $tmpCols);
$thumbHeight = floor($thumbWidth / $ratio);
$mediaQuery = "(min-width: " . $breakpoints[$i]['minWidth'] . "px)";
if(isset($breakpoints[$i + 1]) && is_array($breakpoints[$i + 1])) {
$mediaQuery .= "and (max-width: " . $breakpoints[$i + 1]['minWidth'] . "px)";
}
$medias[$mediaQuery][] = [
"method" => "cover",
"arguments" => [
"width" => $thumbWidth,
"height" => $thumbHeight,
"positioning" => "center",
"forceResize" => true
]
];
}
$conf->setMedias($medias);
return $conf;
}
/**
* Gets Hostname
*
* @return string
*/
public function getHostname(): string
{
return \Pimcore\Tool::getRequestScheme() . '://' . \Pimcore\Tool::getHostname();
}
/**
* Renders a Pimcore Video from a Data Object using document's video tag
*
* @param \Pimcore\Model\DataObject\Data\Video $video
* @param array $config
* @return string
*/
public function videoFromDataobject(\Pimcore\Model\DataObject\Data\Video $video, array $config = []): void
{
$videoData = $video->getData();
if($videoData) {
$videoEditable = new \Pimcore\Model\Document\Editable\Video();
// if no video thumb conf given, set default one
$thumbnailConf = new \Pimcore\Model\Asset\Video\Thumbnail\Config();
$thumbnailConf->setName('default');
if(!isset($config['thumbnail']) || !$config['thumbnail']) {
$config['thumbnail'] = $thumbnailConf;
}
$videoEditable->setConfig($config);
// set data from data object
$videoEditable->setDataFromResource([
'type' => $video->getType(),
'id' => ($videoData instanceof Asset) ? $videoData->getId() : $videoData,
'title' => $video->getTitle(),
'description' => $video->getDescription(),
'poster' => ($video->getPoster() ? $video->getPoster()->getId() : '')
]);
echo $videoEditable->frontend();
}
}
/**
* @param string $icon
* @param bool $inline
* @param bool $asData
* @return string
*/
public function includeSvg(string $icon, bool $inline = false, bool $asData = false): string
{
$svgPaths = [
PIMCORE_WEB_ROOT . '/static/images/layout/svg/',
PIMCORE_WEB_ROOT . '/static/images/icons/'
];
$iconPath = null;
foreach ($svgPaths as $path) {
if(file_exists($path. $icon . '.svg')) {
$iconPath = $path. $icon . '.svg';
break;
}
}
if(!$iconPath) {
return '';
}
$svg = '';
if( $inline || $asData ) {
$svg = file_get_contents($iconPath);
if( $asData ) {
$svg = urlencode($svg);
} else {
$svg = str_replace(PIMCORE_WEB_ROOT, '', $svg);
}
if( !$inline || $asData ) {
$svg = '<img src="data:image/svg+xml;base64,' . base64_encode($svg) . '" />';
}
}
return $svg ?? '';
}
}