<?php
namespace App\Twig\PressSite;
use App\Contract\Media\InternalFileProviderInterface;
use App\Contract\PressSite\Multimedia\MultimediaCollectorInterface;
use App\Entity\AssetOnline;
use App\Entity\AssetOnlineAudioLanguage;
use App\Entity\AssetOnlineSubtitleLanguage;
use App\Entity\Product;
use App\Entity\ProductTVSeries;
use App\Enum\Common\LanguageEnum;
use App\Service\Helper\PressSite\MultimediaHelper;
use App\Service\PressSite\Multimedia\MultimediaFactory;
use Symfony\Component\HttpFoundation\Request;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
/**
* Class MultimediaExtension.
*
* This extension provides helper methods that are only used
* in the PressSites in order to manage all asset and media
* related entries.
*/
class MultimediaExtension extends AbstractExtension
{
/**
* The factory service responsible for creating a multimedia helper service.
*
* @var \App\Service\PressSite\Multimedia\MultimediaFactory
*/
private $multimediaFactory;
/**
* The custom file provider.
*
* @var \App\Media\Provider\AssetFileProvider
*/
private $assetFileProvider;
/**
* The instance of the collector service based on the site type.
*
* @var \App\Contract\PressSite\Multimedia\MultimediaCollectorInterface
*/
private static $multimediaCollector;
public function __construct(MultimediaFactory $multimediaFactory, InternalFileProviderInterface $assetFileProvider)
{
$this->multimediaFactory = $multimediaFactory;
$this->assetFileProvider = $assetFileProvider;
}
public function getFunctions(): array
{
return [
new TwigFunction('getAssetResolution', [$this, 'getAssetResolution']),
new TwigFunction('getProductAssets', [$this, 'getProductAssets']),
new TwigFunction('getAssetPoster', [$this, 'getAssetPoster']),
new TwigFunction('getAssetFilesize', [$this, 'getAssetFilesize']),
new TwigFunction('getAssetOriginalUrl', [$this, 'getAssetOriginalUrl']),
new TwigFunction('isAssetSelected', [$this, 'isAssetSelected']),
new TwigFunction('getAssetAudioLanguages', [$this, 'getAssetAudioLanguages']),
new TwigFunction('getAssetSubtitleLanguages', [$this, 'getAssetSubtitleLanguages']),
];
}
/**
* Returns the collection of product assets grouped by tab name.
*
* @param \App\Entity\Product $entity
* The instance of the loaded product
*
* @return array
* The collection of assets
*/
public function getProductAssets(Product $entity): array
{
$seriesId = ($entity instanceof ProductTVSeries && !empty($entity->getSeries()))
? $entity->getSeries()->getSeriesID()
: null;
return $this->getMultimediaCollector()->collectAssets(
$entity->getProductID(),
$seriesId
);
}
/**
* Responsible for returning the correct poster for the fancybox modal.
*
* We have a lot of asset content types with no generated thumbnail,
* so this helper method will take into consideration whether we operate
* on an asset with specific extension (one that have generated thumbnail)
* or not and return a default photo instead.
*
* @param \App\Entity\AssetOnline $entity
* The instance of the loaded asset
*
* @return string
* The url of the poster
*/
public function getAssetPoster(AssetOnline $entity): string
{
if (!in_array($entity->getExtension(), ['jpg', 'jpeg', 'png'])) {
return '/assets/press_site/images/default-cover-image.jpg';
}
return $this->assetFileProvider->generatePublicUrl($entity->getFile(), 'default_pr_poster');
}
/**
* Returnn the url to the original asset.
*
* @param \App\Entity\AssetOnline $entity
* The instance of the loaded asset
*
* @return string
* The full url for the originally uploaded asset
*/
public function getAssetOriginalUrl(AssetOnline $entity): string
{
return $this->assetFileProvider->generatePublicUrl($entity->getFile(), 'reference');
}
/**
* Returns the human readable formatted file size.
*
* @param \App\Entity\AssetOnline $entity
* The instance of the loaded asset
*
* @return string|null
* The formatted filesize
*/
public function getAssetFilesize(AssetOnline $entity): ?string
{
$bytes = $entity->getFile()->getSize();
if (0 >= $bytes) {
return null;
}
$i = floor(log($bytes, 1024));
$units = ['B', 'kB', 'MB', 'GB', 'TB'];
$steps = [0, 0, 2, 2, 3];
return round($bytes / 1024 ** $i, $steps[$i]) . $units[$i];
}
/**
* Returns comma delimited list of audio languages.
*
* @param \App\Entity\AssetOnline $entity
* The instance of the loaded asset
*
* @return string|null
* comma delimited string
*/
public function getAssetAudioLanguages(AssetOnline $entity): ?string
{
$languages = $entity->getAudioLanguages()->map(fn (AssetOnlineAudioLanguage $audioLanguage) => LanguageEnum::readableFor($audioLanguage->getLanguage()))->toArray();
return implode(', ', $languages);
}
/**
* Returns comma delimited list of subtitle languages.
*
* @param \App\Entity\AssetOnline $entity
* The instance of the loaded asset
*
* @return string|null
* comma delimited string
*/
public function getAssetSubtitleLanguages(AssetOnline $entity): ?string
{
$languages = $entity->getSubtitleLanguages()->map(fn (AssetOnlineSubtitleLanguage $subLanguage) => LanguageEnum::readableFor($subLanguage->getLanguage()));
$languages = $languages->toArray();
return implode(', ', $languages);
}
/**
* Returns Asset Resolution Aspect.
*
* @return string|null
*/
public function getAssetResolution(AssetOnline $entity): string
{
return $entity->getAssetResolutionAspect()->getName();
}
/**
* Indicates whether or not given asset is added to session storage for download.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The current request object
* @param int $productId
* The ID of the currently loaded product
* @param int $assetId
* The ID of the currently processed asset
*
* @return bool
* The check result
*/
public function isAssetSelected(Request $request, int $productId, int $assetId): bool
{
$request->attributes->set('_product_id', $productId);
$data = $request->getSession()->get(MultimediaHelper::createStorageKey($request));
return !empty($data) && !empty($data['items']) && isset($data['items'][$assetId]);
}
/**
* Returns an instance of the multimedia collector service based on the current site typ.
*
* @return \App\Contract\PressSite\Multimedia\MultimediaCollectorInterface
* The instance of the class implementing this interface
*/
protected function getMultimediaCollector(): MultimediaCollectorInterface
{
if (!static::$multimediaCollector instanceof MultimediaCollectorInterface) {
static::$multimediaCollector = $this->multimediaFactory->createCollector();
}
return static::$multimediaCollector;
}
}