Completed
Push — master ( 0be8e1...585ca2 )
by Daniel
59:26 queued 46:02
created

FileInterfaceSubscriber::processNewEntities()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 10
nc 5
nop 2
dl 0
loc 16
rs 9.2222
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Silverback\ApiComponentBundle\EventSubscriber\EntitySubscriber;
6
7
use Doctrine\DBAL\Platforms\SqlitePlatform;
8
use Doctrine\ORM\EntityManagerInterface;
9
use Doctrine\ORM\Event\OnFlushEventArgs;
10
use Doctrine\ORM\UnitOfWork;
11
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
12
use Liip\ImagineBundle\Service\FilterService;
13
use Silverback\ApiComponentBundle\Entity\Component\FileInterface;
14
use Silverback\ApiComponentBundle\Entity\SortableInterface;
15
use Silverback\ApiComponentBundle\Imagine\PathResolver;
16
use Silverback\ApiComponentBundle\Validator\ImagineSupportedFilePath;
17
18
class FileInterfaceSubscriber implements EntitySubscriberInterface
19
{
20
    /**
21
     * @var CacheManager
22
     */
23
    private $imagineCacheManager;
24
    /**
25
     * @var FilterService
26
     */
27
    private $filterService;
28
    /**
29
     * @var PathResolver
30
     */
31
    private $pathResolver;
32
33
    /**
34
     * @param CacheManager $imagineCacheManager
35
     * @param FilterService $filterService
36
     * @param PathResolver $pathResolver
37
     */
38
    public function __construct(
39
        CacheManager $imagineCacheManager,
40
        FilterService $filterService,
41
        PathResolver $pathResolver
42
    ) {
43
        $this->imagineCacheManager = $imagineCacheManager;
44
        $this->filterService = $filterService;
45
        $this->pathResolver = $pathResolver;
46
    }
47
48
    /**
49
     * @return array
50
     */
51
    public function getSubscribedEvents(): array
52
    {
53
        return [
54
            'onFlush'
55
        ];
56
    }
57
58
    public function supportsEntity($entity = null): bool
59
    {
60
        return true;
61
    }
62
63
    /**
64
     * @param OnFlushEventArgs $eventArgs
65
     */
66
    public function onFlush(OnFlushEventArgs $eventArgs): void
67
    {
68
        $entityManager = $eventArgs->getEntityManager();
69
        if ($entityManager->getConnection()->getDatabasePlatform() instanceof SqlitePlatform) {
70
            $entityManager->getConnection()->exec('PRAGMA foreign_keys = ON;');
71
        }
72
        $unitOfWork = $entityManager->getUnitOfWork();
73
        $this->processNewEntities($unitOfWork, $entityManager);
74
        $this->processUpdatedEntities($unitOfWork);
75
        $this->processDeletedEntities($unitOfWork);
76
    }
77
78
    /**
79
     * @param UnitOfWork $unitOfWork
80
     * @param EntityManagerInterface $entityManager
81
     */
82
    private function processNewEntities(UnitOfWork $unitOfWork, EntityManagerInterface $entityManager): void
83
    {
84
        $newEntities = $unitOfWork->getScheduledEntityInsertions();
85
        foreach ($newEntities as $entity) {
86
            // This should not really be used here, it won't be fired as validation would fail first
87
            // Dynamic pages sort values need work with auto-calculating
88
            if ($entity instanceof SortableInterface && $entity->getSort() === null) {
89
                $entity->setSort($entity->calculateSort(true));
90
                $metadata = $entityManager->getClassMetadata(\get_class($entity));
91
                $unitOfWork->recomputeSingleEntityChangeSet($metadata, $entity);
92
            }
93
            if (
94
                $entity instanceof FileInterface &&
95
                ImagineSupportedFilePath::isValidFilePath($entity->getFilePath())
96
            ) {
97
                $this->createFilteredImages($entity);
98
            }
99
        }
100
    }
101
102
    /**
103
     * @param UnitOfWork $unitOfWork
104
     */
105
    private function processUpdatedEntities(UnitOfWork $unitOfWork): void
106
    {
107
        $updatedEntities = $unitOfWork->getScheduledEntityUpdates();
108
        foreach ($updatedEntities as $entity) {
109
            if ($entity instanceof FileInterface) {
110
                $changes = $unitOfWork->getEntityChangeSet($entity);
111
                if (!\is_array($changes)) {
112
                    return;
113
                }
114
                if (array_key_exists('filePath', $changes)) {
115
                    $fpChanges = $changes['filePath'];
116
                    $previousValueForField = $fpChanges[0] ?? null;
117
                    $newValueForField = $fpChanges[1] ?? null;
118
                    if ($previousValueForField !== $newValueForField) {
119
                        if ($previousValueForField !== null && file_exists($previousValueForField)) {
120
                            unlink($previousValueForField);
121
                        }
122
                        if (ImagineSupportedFilePath::isValidFilePath($previousValueForField)) {
123
                            $this->imagineCacheManager->remove($previousValueForField);
124
                        }
125
                        if (ImagineSupportedFilePath::isValidFilePath($newValueForField)) {
126
                            $this->createFilteredImages($entity);
127
                        }
128
                    }
129
                }
130
            }
131
        }
132
    }
133
134
    /**
135
     * @param UnitOfWork $unitOfWork
136
     */
137
    private function processDeletedEntities(UnitOfWork $unitOfWork): void
138
    {
139
        $deletedEntities = $unitOfWork->getScheduledEntityDeletions();
140
        foreach ($deletedEntities as $entity) {
141
            if ($entity instanceof FileInterface) {
142
                if (($filePath = $entity->getFilePath()) && file_exists($filePath)) {
143
                    unlink($filePath);
144
                }
145
                if (ImagineSupportedFilePath::isValidFilePath($entity->getFilePath())) {
146
                    $this->imagineCacheManager->remove($entity->getFilePath());
147
                }
148
            }
149
        }
150
    }
151
152
    private function createFilteredImages(FileInterface $file): void
153
    {
154
        $filters = $file::getImagineFilters();
155
        foreach ($filters as $filter) {
156
            $this->filterService->getUrlOfFilteredImage($this->pathResolver->resolve($file->getFilePath()), $filter);
157
        }
158
    }
159
}
160