Repository URL to install this package:
|
Version:
6.3.0 ▾
|
<?php
namespace DigitalAscetic\FileBundle\EventListener;
use DigitalAscetic\FileBundle\Entity\File\FileEntity;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Events;
use Doctrine\ORM\UnitOfWork;
use Doctrine\Common\Util\ClassUtils;
use Gaufrette\Filesystem;
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use Psr\Log\LoggerInterface;
use Symfony\Component\Config\Definition\Exception\Exception;
/**
* Class FileEntitySubscriber
* @package DigitalAscetic\FileBundle\EventListener
*/
class FileEntitySubscriber implements EventSubscriber
{
/**
* @var string
*/
private ?string $oldPath = null;
/**
* @var array
*/
private $fileEntities;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var CacheManager $cacheManager
*/
private $cacheManager;
/** @var Filesystem */
private $publicFilesystem;
/** @var Filesystem */
private $privateFilesystem;
/**
* FileEntitySubscriber constructor.
*
* @param Filesystem $publicFilesystem
* @param Filesystem $privateFilesystem
* @param array $fileEntities
* @param LoggerInterface $logger
* @param CacheManager $cacheManager
*/
public function __construct(Filesystem $publicFilesystem, Filesystem $privateFilesystem, array $fileEntities, LoggerInterface $logger, CacheManager $cacheManager)
{
$this->publicFilesystem = $publicFilesystem;
$this->privateFilesystem = $privateFilesystem;
$this->fileEntities = $fileEntities;
$this->logger = $logger;
$this->cacheManager = $cacheManager;
}
/**
* @return array
*/
public function getSubscribedEvents(): array
{
return array(
Events::onFlush
);
}
/**
* @param OnFlushEventArgs $args
*/
public function onFlush(OnFlushEventArgs $args)
{
$em = $args->getObjectManager();
$uow = $em->getUnitOfWork();
foreach ($uow->getScheduledEntityInsertions() as $entity) {
if ($this->isFileEntity($entity)) {
$this->handleSyncableFileEntity($entity, $em, $uow);
}
}
foreach ($uow->getScheduledEntityUpdates() as $entity) {
if ($this->isFileEntity($entity)) {
$this->handleSyncableFileEntity($entity, $em, $uow);
}
}
foreach ($uow->getScheduledEntityDeletions() as $entity) {
if ($this->isFileEntity($entity)) {
$this->handleRemoveFileEntity($entity, $em);
}
}
}
private function handleSyncableFileEntity(FileEntity $fileEntity, EntityManagerInterface $em, UnitOfWork $uow)
{
$refClass = ClassUtils::getClass($fileEntity);
$meta = $em->getClassMetadata($refClass);
if ($fileEntity->isSyncWithCanonicalPath()) {
$this->syncPathWithCanonicalPath($fileEntity);
if ($uow->isInIdentityMap($fileEntity)) {
$uow->recomputeSingleEntityChangeSet($meta, $fileEntity);
} else {
$em->persist($fileEntity);
$uow->computeChangeSet($meta, $fileEntity);
}
}
if ($this->oldPath) {
$this->renameFileEntity($fileEntity, $em);
}
}
private function handleRemoveFileEntity(FileEntity $fileEntity, EntityManagerInterface $em)
{
/** @var Filesystem $publicFileSystem */
$filesystem = null;
if ($fileEntity->getFile()->getPublic()) {
$filesystem = $this->publicFilesystem;
} else {
$filesystem = $this->privateFilesystem;
}
if ($fileEntity->isSyncWithCanonicalPath()) {
$canonicalPath = $fileEntity->getCanonicalPath();
try {
if ($filesystem->has($canonicalPath)) {
$filesystem->delete($canonicalPath);
}
foreach ($fileEntity->getRelatedPaths() as $relatedPath) {
if ($filesystem->has($relatedPath)) {
$filesystem->delete($relatedPath);
}
}
} catch (Exception $e) {
$em->close();
$em->getConnection()->rollback();
throw $e;
}
//We need to transform uri to path for correct check cacheManage store cached
// eg: pub/fr/1/agency/1/realestate/234232/images/131331312.jpg
$path = parse_url($fileEntity->getFile()->getUri())['path'];
//Remove first / from path
$path = ltrim($path, '/');
$this->cacheManager->remove($path);
}
}
private function stripInitialSlash($path)
{
if (str_starts_with($path, '/')) {
$path = substr($path, 1);
}
return $path;
}
private function syncPathWithCanonicalPath(FileEntity $fileEntity)
{
$canonicalPath = $this->stripInitialSlash($fileEntity->getCanonicalPath());
$path = $this->stripInitialSlash($fileEntity->getFile()->getPath());
if ($canonicalPath != $path) {
// Strip initial "/" as Gaufrette wants the source key relative to root path
$this->oldPath = $path;
$fileEntity->getFile()->setPath($canonicalPath);
}
}
private function isManagedFileEntity($entity): bool
{
return ($this->isFileEntity($entity));
}
private function isFileEntity($entity): bool
{
return ($entity instanceof FileEntity);
}
private function renameFileEntity(FileEntity $fileEntity, EntityManagerInterface $em)
{
if ($fileEntity->getFile()->getPublic()) {
$filesystem = $this->publicFilesystem;
} else {
$filesystem = $this->privateFilesystem;
}
try {
$canonicalPath = $fileEntity->getCanonicalPath();
if ($this->oldPath && $filesystem->has($this->oldPath)) {
$filesystem->rename($this->oldPath, $canonicalPath, 1);
}
} catch (Exception $e) {
$em->close();
$em->getConnection()->rollback();
throw $e;
}
$this->oldPath = null;
}
}