Passed
Pull Request — master (#58)
by Daniel
06:55 queued 01:16
created

MediaObjectFactory::createMediaObjects()   A

Complexity

Conditions 6
Paths 10

Size

Total Lines 29
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
cc 6
eloc 17
nc 10
nop 1
dl 0
loc 29
ccs 0
cts 17
cp 0
crap 42
rs 9.0777
c 0
b 0
f 0
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\Utility\ImagineFiltersInterface;
24
use Silverback\ApiComponentsBundle\Flysystem\FilesystemProvider;
25
use Silverback\ApiComponentsBundle\Imagine\FlysystemDataLoader;
26
use Silverback\ApiComponentsBundle\Model\Uploadable\MediaObject;
27
use Silverback\ApiComponentsBundle\Uploadable\FileInfoCacheHelper;
28
use Silverback\ApiComponentsBundle\Utility\ClassMetadataTrait;
29
use Symfony\Component\HttpFoundation\RequestStack;
30
31
/**
32
 * @author Daniel West <[email protected]>
33
 */
34
class MediaObjectFactory
35
{
36
    use ClassMetadataTrait;
37
38
    private FileInfoCacheHelper $fileInfoCacheHelper;
39
    private UploadableAnnotationReader $annotationReader;
40
    private FilesystemProvider $filesystemProvider;
41
    private FlysystemDataLoader $flysystemDataLoader;
42
    private RequestStack $requestStack;
43
    private ?FilterService $filterService;
44
45
    public function __construct(
46
        ManagerRegistry $managerRegistry,
47
        FileInfoCacheHelper $fileInfoCacheHelper,
48
        UploadableAnnotationReader $annotationReader,
49
        FilesystemProvider $filesystemProvider,
50
        FlysystemDataLoader $flysystemDataLoader,
51
        RequestStack $requestStack,
52
        ?FilterService $filterService = null
53
    ) {
54
        $this->initRegistry($managerRegistry);
55
        $this->fileInfoCacheHelper = $fileInfoCacheHelper;
56
        $this->annotationReader = $annotationReader;
57
        $this->filesystemProvider = $filesystemProvider;
58
        $this->flysystemDataLoader = $flysystemDataLoader;
59
        $this->requestStack = $requestStack;
60
        $this->filterService = $filterService;
61
    }
62
63
    public function createMediaObjects(object $object): ?ArrayCollection
64
    {
65
        $collection = new ArrayCollection();
66
        $classMetadata = $this->getClassMetadata($object);
67
68
        $configuredProperties = $this->annotationReader->getConfiguredProperties($object, true, true);
69
        foreach ($configuredProperties as $fileProperty => $fieldConfiguration) {
70
            $propertyMediaObjects = [];
71
            $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

71
            $filesystem = $this->filesystemProvider->getFilesystem(/** @scrutinizer ignore-type */ $fieldConfiguration->adapter);
Loading history...
72
            $path = $classMetadata->getFieldValue($object, $fieldConfiguration->property);
73
            if (!$path) {
74
                continue;
75
            }
76
            if (!$filesystem->fileExists($path)) {
77
                continue;
78
            }
79
80
            // Populate the primary MediaObject
81
            try {
82
                $propertyMediaObjects[] = $this->create($filesystem, $path);
83
            } catch (UnableToReadFile $exception) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
84
            }
85
86
            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

86
            array_push($propertyMediaObjects, ...$this->getMediaObjectsForImagineFilters($object, $path, /** @scrutinizer ignore-type */ $fieldConfiguration, $fileProperty));
Loading history...
87
88
            $collection->set($fieldConfiguration->property, $propertyMediaObjects);
89
        }
90
91
        return $collection->count() ? $collection : null;
92
    }
93
94
    /**
95
     * @return MediaObject[]
96
     */
97
    private function getMediaObjectsForImagineFilters(object $object, string $path, UploadableField $uploadableField, string $fileProperty): array
98
    {
99
        $mediaObjects = [];
100
        if (!$this->filterService) {
101
            return $mediaObjects;
102
        }
103
104
        // Let the data loader which should be configured for imagine to know which adapter to use
105
        $this->flysystemDataLoader->setAdapter($uploadableField->adapter);
106
107
        $filters = $uploadableField->imagineFilters;
108
        if ($object instanceof ImagineFiltersInterface) {
109
            $request = $this->requestStack->getMasterRequest();
110
            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

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