Passed
Pull Request — master (#58)
by Daniel
06:59
created

MediaObjectFactory::populateMediaObjectFromCache()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 5
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 8
ccs 0
cts 6
cp 0
crap 2
rs 10
1
<?php
2
3
/*
4
 * This file is part of the Silverback API Components Bundle Project
5
 *
6
 * (c) Daniel West <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Silverback\ApiComponentsBundle\Factory\Uploadable;
15
16
use Doctrine\Common\Collections\ArrayCollection;
17
use Doctrine\Persistence\ManagerRegistry;
18
use League\Flysystem\Filesystem;
19
use League\Flysystem\UnableToReadFile;
20
use Liip\ImagineBundle\Service\FilterService;
21
use Silverback\ApiComponentsBundle\Annotation\UploadableField;
22
use Silverback\ApiComponentsBundle\AnnotationReader\UploadableAnnotationReader;
23
use Silverback\ApiComponentsBundle\Entity\Core\FileInfo;
24
use Silverback\ApiComponentsBundle\Entity\Utility\ImagineFiltersInterface;
25
use Silverback\ApiComponentsBundle\Flysystem\FilesystemProvider;
26
use Silverback\ApiComponentsBundle\Imagine\FlysystemDataLoader;
27
use Silverback\ApiComponentsBundle\Model\Uploadable\MediaObject;
28
use Silverback\ApiComponentsBundle\Uploadable\FileInfoCacheHelper;
29
use Silverback\ApiComponentsBundle\Utility\ClassMetadataTrait;
30
use Symfony\Component\HttpFoundation\RequestStack;
31
32
/**
33
 * @author Daniel West <[email protected]>
34
 */
35
class MediaObjectFactory
36
{
37
    use ClassMetadataTrait;
38
39
    private FileInfoCacheHelper $fileInfoCacheHelper;
40
    private UploadableAnnotationReader $annotationReader;
41
    private FilesystemProvider $filesystemProvider;
42
    private FlysystemDataLoader $flysystemDataLoader;
43
    private RequestStack $requestStack;
44
    private ?FilterService $filterService;
45
46
    public function __construct(
47
        ManagerRegistry $managerRegistry,
48
        FileInfoCacheHelper $fileInfoCacheHelper,
49
        UploadableAnnotationReader $annotationReader,
50
        FilesystemProvider $filesystemProvider,
51
        FlysystemDataLoader $flysystemDataLoader,
52
        RequestStack $requestStack,
53
        ?FilterService $filterService = null
54
    ) {
55
        $this->initRegistry($managerRegistry);
56
        $this->fileInfoCacheHelper = $fileInfoCacheHelper;
57
        $this->annotationReader = $annotationReader;
58
        $this->filesystemProvider = $filesystemProvider;
59
        $this->flysystemDataLoader = $flysystemDataLoader;
60
        $this->requestStack = $requestStack;
61
        $this->filterService = $filterService;
62
    }
63
64
    public function createMediaObjects(object $object): ?ArrayCollection
65
    {
66
        $collection = new ArrayCollection();
67
        $classMetadata = $this->getClassMetadata($object);
68
69
        $configuredProperties = $this->annotationReader->getConfiguredProperties($object, true, true);
70
        foreach ($configuredProperties as $fileProperty => $fieldConfiguration) {
71
            $propertyMediaObjects = [];
72
            $filesystem = $this->filesystemProvider->getFilesystem($fieldConfiguration->adapter);
0 ignored issues
show
Bug introduced by
It seems like $fieldConfiguration->adapter can also be of type null; however, parameter $name of Silverback\ApiComponents...ovider::getFilesystem() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

72
            $filesystem = $this->filesystemProvider->getFilesystem(/** @scrutinizer ignore-type */ $fieldConfiguration->adapter);
Loading history...
73
            $path = $classMetadata->getFieldValue($object, $fieldConfiguration->property);
74
            if (!$path) {
75
                continue;
76
            }
77
            if (!$filesystem->fileExists($path)) {
78
                continue;
79
            }
80
81
            // Populate the primary MediaObject
82
            try {
83
                $propertyMediaObjects[] = $this->create($filesystem, $path);
84
            } catch (UnableToReadFile $exception) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
85
            }
86
87
            array_push($propertyMediaObjects, ...$this->getMediaObjectsForImagineFilters($object, $path, $fieldConfiguration, $fileProperty));
0 ignored issues
show
Bug introduced by
It seems like $fieldConfiguration can also be of type string; however, parameter $uploadableField of Silverback\ApiComponents...ectsForImagineFilters() does only seem to accept Silverback\ApiComponents...otation\UploadableField, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

87
            array_push($propertyMediaObjects, ...$this->getMediaObjectsForImagineFilters($object, $path, /** @scrutinizer ignore-type */ $fieldConfiguration, $fileProperty));
Loading history...
88
89
            $collection->set($fieldConfiguration->property, $propertyMediaObjects);
90
        }
91
92
        return $collection->count() ? $collection : null;
93
    }
94
95
    /**
96
     * @return MediaObject[]
97
     */
98
    private function getMediaObjectsForImagineFilters(object $object, string $path, UploadableField $uploadableField, string $fileProperty): array
99
    {
100
        $mediaObjects = [];
101
        if (!$this->filterService) {
102
            return $mediaObjects;
103
        }
104
105
        // Let the data loader which should be configured for imagine to know which adapter to use
106
        $this->flysystemDataLoader->setAdapter($uploadableField->adapter);
107
108
        $filters = $uploadableField->imagineFilters;
109
        if ($object instanceof ImagineFiltersInterface) {
110
            $request = $this->requestStack->getMasterRequest();
111
            array_push($filters, ...$object->getImagineFilters($fileProperty, $request));
0 ignored issues
show
Bug introduced by
It seems like $filters can also be of type null; however, parameter $array of array_push() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

111
            array_push(/** @scrutinizer ignore-type */ $filters, ...$object->getImagineFilters($fileProperty, $request));
Loading history...
112
        }
113
114
        foreach ($filters as $filter) {
115
            $resolvedUrl = $this->filterService->getUrlOfFilteredImage($path, $filter);
116
            $mediaObjects[] = $this->createFromImagine($resolvedUrl, $path, $filter);
117
        }
118
119
        return $mediaObjects;
120
    }
121
122
    private function create(Filesystem $filesystem, string $filename): MediaObject
123
    {
124
        $mediaObject = new MediaObject();
125
        $mediaObject->contentUrl = 'https://www.website.com/path';
126
        $mediaObject->imagineFilter = null;
127
128
        $fileInfo = $this->fileInfoCacheHelper->resolveCache($filename);
129
        if ($fileInfo) {
130
            return $this->populateMediaObjectFromCache($mediaObject, $fileInfo);
131
        }
132
133
        $mediaObject->fileSize = $filesystem->fileSize($filename);
134
        $mediaObject->mimeType = $filesystem->mimeType($filename);
135
        if (false !== strpos($mediaObject->mimeType, 'image/')) {
136
            $file = $filesystem->read($filename);
137
            if ('image/svg+xml' === $mediaObject->mimeType) {
138
                $xmlget = simplexml_load_string(file_get_contents($file));
139
                $xmlattributes = $xmlget->attributes();
140
                $mediaObject->width = (int) $xmlattributes->width;
141
                $mediaObject->height = (int) $xmlattributes->height;
142
            } else {
143
                [ $mediaObject->width, $mediaObject->height ] = @getimagesize($file);
144
            }
145
        }
146
147
        $fileInfo = new FileInfo($filename, $mediaObject->mimeType, $mediaObject->fileSize, $mediaObject->width, $mediaObject->height);
148
        $this->fileInfoCacheHelper->saveCache($fileInfo);
149
150
        return $mediaObject;
151
    }
152
153
    private function createFromImagine(string $contentUrl, string $path, string $imagineFilter): MediaObject
154
    {
155
        $mediaObject = new MediaObject();
156
        $mediaObject->contentUrl = $contentUrl;
157
        $mediaObject->imagineFilter = $imagineFilter;
158
159
        $fileInfo = $this->fileInfoCacheHelper->resolveCache($path, $imagineFilter);
160
        if ($fileInfo) {
161
            return $this->populateMediaObjectFromCache($mediaObject, $fileInfo);
162
        }
163
        $mediaObject->width = $mediaObject->height = $mediaObject->fileSize = -1;
164
        $mediaObject->mimeType = '';
165
166
        return $mediaObject;
167
    }
168
169
    private function populateMediaObjectFromCache(MediaObject $mediaObject, FileInfo $fileInfo): MediaObject
170
    {
171
        $mediaObject->fileSize = $fileInfo->fileSize;
172
        $mediaObject->mimeType = $fileInfo->mimeType;
173
        $mediaObject->width = $fileInfo->width;
174
        $mediaObject->height = $fileInfo->height;
175
176
        return $mediaObject;
177
    }
178
}
179