<?php
namespace App\EventListener;
use App\Service\Validator\Asset\NamingValidator;
use Pimcore\Event\Model\Asset\ResolveUploadTargetEvent;
use Pimcore\Event\Model\AssetEvent;
use Pimcore\Logger;
use Pimcore\Model\Asset;
use Pimcore\Model\DataObject\Data\Hotspotimage;
use Pimcore\Model\DataObject\Data\ImageGallery;
use Pimcore\Model\DataObject\Good;
class AssetListener
{
private static bool $fileRewrite = false;
private NamingValidator $namingValidator;
private array $assetsPossibleTypesToUpdateMethods = [
'preview' => 'updatePreview',
'preview_flip' => 'updatePreviewFlip',
'gallery' => 'updateGallery',
'white' => 'updateWhite',
'gray' => 'updateGray',
'panorama' => 'updatePanorama',
'model' => 'update3DModel',
'scheme' => 'updateSchemes',
'manual' => 'updateManuals'
];
public function __construct(NamingValidator $namingValidator)
{
$this->namingValidator = $namingValidator;
}
// event handlers
public function onResolveUploadTarget(ResolveUploadTargetEvent $ev)
{
if ( isset($ev->getContext()['containerType']) ){
//Если asset залит через родительский объект
//@todo автозаливка файлов в связанную с объектом папку
}else{
if (isset($ev->getContext()['fromZip']) && $ev->getContext()['fromZip'] === true) {
//Загрузка архива в списке ассетов
$this->processUnzippedFile($ev->getFilename(), $ev->getParentId());
} elseif ( !is_null($ev->getParentId()) ){
$this->deleteAssetIfExists($ev->getParentId());
}
}
}
public function onPostAdd(AssetEvent $ev)
{
$asset = $ev->getAsset();
$ftype = $this->detectPossibleFileTypeByName($asset->getFilename());
if (!$ftype) return;
$methodName = $this->assetsPossibleTypesToUpdateMethods[$ftype] ?? '';
if (method_exists($this, $methodName) && $this->assetMeetsNamingRequirements($asset, $ftype)) $this->$methodName($asset);
}
// resolveUploadTarget methods
private function deleteAssetIfExists(int $goodAssetsFolderId)
{
$goodAssetFolder = Asset::getById($goodAssetsFolderId);
$good = Good::getByAssetFolder($goodAssetFolder)->getObjects();
if (!$good) return;
$goodAssets = $goodAssetFolder->getChildren();
$existing = array_filter($goodAssets, fn($goodAsset) => $goodAsset->getFilename() === $_FILES['Filedata']['name']);
$existing = $existing ? array_values($existing)[0] : $existing;
if (!$existing) return;
self::$fileRewrite = true;
$existing->delete();
}
private function processUnzippedFile($fileName, $parentId)
{
$currentAssets = Asset::getById($parentId)->getChildren();
$targetAsset = array_filter($currentAssets, fn($asset) => $asset->getFilename() === $fileName);
if ($targetAsset) array_values($targetAsset)[0]->delete();
}
// postAdd methods
private function detectPossibleFileTypeByName($fName)
{
if (str_contains($fName, 'preview_flip')) return 'preview_flip';
$fNameParts = explode('_', $fName);
if (count($fNameParts) <= 1) return false;
foreach ($this->assetsPossibleTypesToUpdateMethods as $type => $method) {
foreach ($fNameParts as $part) {
if (str_contains($part, $type)) {
return $type;
}
}
}
return false;
}
private function updatePreview(Asset $asset)
{
$good = Good::getByAssetFolder($asset->getParent())->getObjects();
if (!$good) return;
$good = $good[0];
$marketingBrick = $good->getMarketingProps()->getMarketingBrick();
$marketingBrick->setPreviewImg($asset);
$good->save();
}
private function updatePreviewFlip(Asset $asset)
{
$good = Good::getByAssetFolder($asset->getParent())->getObjects();
if (!$good) return;
$good = $good[0];
$marketingBrick = $good->getMarketingProps()->getMarketingBrick();
$marketingBrick->setPreviewImgFlip($asset);
$good->save();
}
private function updateGallery(Asset $asset)
{
$goodAssetFolder = $asset->getParent();
$good = Good::getByAssetFolder($goodAssetFolder)->getObjects();
if (!$good) return;
$good = $good[0];
$goodAssets = $goodAssetFolder->getChildren();
$galleryAssets = array_values(array_filter($goodAssets, fn($goodAsset) => str_contains($goodAsset->getFilename(), '_gallery_')));
$galleryAssets = $this->processSpecificAssetsArray($asset, $galleryAssets, self::$fileRewrite);
$galleryItems = array_map(function($galleryAsset){
$hotSpotImg = new Hotspotimage();
$hotSpotImg->setImage($galleryAsset);
return $hotSpotImg;
}, $galleryAssets);
$gallery = new ImageGallery($galleryItems);
$marketingBrick = $good->getMarketingProps()->getMarketingBrick();
$marketingBrick->setGallery($gallery);
$good->save();
}
private function updateWhite(Asset $asset)
{
$good = Good::getByAssetFolder($asset->getParent())->getObjects();
if (!$good) return;
$good = $good[0];
$marketingBrick = $good->getMarketingProps()->getMarketingBrick();
$marketingBrick->setMainPhotoWhite($asset);
$good->save();
}
private function updateGray(Asset $asset)
{
$good = Good::getByAssetFolder($asset->getParent())->getObjects();
if (!$good) return;
$good = $good[0];
$marketingBrick = $good->getMarketingProps()->getMarketingBrick();
$marketingBrick->setMainPhotoGray($asset);
$good->save();
}
private function updatePanorama(Asset $asset)
{
$good = Good::getByAssetFolder($asset->getParent())->getObjects();
if (!$good) return;
$good = $good[0];
$marketingBrick = $good->getMarketingProps()->getMarketingBrick();
$marketingBrick->setPanoramaGIF($asset);
$good->save();
}
private function update3DModel(Asset $asset)
{
$good = Good::getByAssetFolder($asset->getParent())->getObjects();
if (!$good) return;
$good = $good[0];
$marketingBrick = $good->getMarketingProps()->getMarketingBrick();
$marketingBrick->setModel3d($asset);
$good->save();
}
private function updateSchemes(Asset $asset)
{
$goodAssetFolder = $asset->getParent();
$good = Good::getByAssetFolder($goodAssetFolder)->getObjects();
if (!$good) return;
$good = $good[0];
$goodAssets = $goodAssetFolder->getChildren();
$schemasAssets = array_values(array_filter($goodAssets, fn($goodAsset) => str_contains($goodAsset->getFilename(), '_scheme_')));
$schemasAssets = $this->processSpecificAssetsArray($asset, $schemasAssets, self::$fileRewrite);
$schemasItems = array_map(function($galleryAsset){
$hotSpotImg = new Hotspotimage();
$hotSpotImg->setImage($galleryAsset);
return $hotSpotImg;
}, $schemasAssets);
$schemas = new ImageGallery($schemasItems);
$marketingBrick = $good->getMarketingProps()->getMarketingBrick();
$marketingBrick->setSchemes($schemas);
$good->save();
}
private function updateManuals(Asset $asset)
{
$goodAssetFolder = $asset->getParent();
$good = Good::getByAssetFolder($goodAssetFolder)->getObjects();
if (!$good) return;
$good = $good[0];
$goodAssets = $goodAssetFolder->getChildren();
$manualsAssets = array_filter($goodAssets, fn($asset)=> str_contains($asset->getFilename(), '_manual_'));
$manualsAssets = $this->processSpecificAssetsArray($asset, $manualsAssets, self::$fileRewrite);
$marketingBrick = $good->getMarketingProps()->getMarketingBrick();
$marketingBrick->setManuals($manualsAssets);
$good->save();
}
private function processSpecificAssetsArray(Asset $currentAsset, $assets = [], $isRewrite = false) : array
{
$out = $assets;
if ($assets) {
if ($isRewrite) {
$rewritingFileIndex = array_search($currentAsset->getFilename(), array_map(fn($arrayAsset) => $arrayAsset ? $arrayAsset->getFilename() : false, $assets));
if ($rewritingFileIndex !== false) {
$out[$rewritingFileIndex] = $currentAsset;
} else {
$out[] = $currentAsset;
}
} else {
$out[] = $currentAsset;
}
} else {
$out = [$currentAsset];
}
return $out;
}
private function assetMeetsNamingRequirements(Asset $asset, string $type = ""): bool
{
$good = Good::getByAssetFolder($asset->getParent())->getObjects();
if (!$good) return false;
$this->namingValidator->setAsset($asset);
return $this->namingValidator->validateByType($type, $good[0]->getArticle());
}
}