Passed
Push — develop ( 4ccf1b...14897c )
by Daniel
04:51
created

ApiNormalizer::isImagineSupportedFile()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.0261

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 1
dl 0
loc 11
ccs 6
cts 7
cp 0.8571
crap 3.0261
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Silverback\ApiComponentBundle\Serializer;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
7
use Silverback\ApiComponentBundle\Entity\Content\Component\Form\Form;
8
use Silverback\ApiComponentBundle\Entity\Content\FileInterface;
9
use Silverback\ApiComponentBundle\Entity\Content\Page;
10
use Silverback\ApiComponentBundle\Entity\Layout\Layout;
11
use Silverback\ApiComponentBundle\Factory\Entity\Content\Component\Form\FormViewFactory;
12
use Silverback\ApiComponentBundle\Imagine\PathResolver;
13
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
14
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
15
use Symfony\Component\Serializer\SerializerAwareInterface;
16
use Symfony\Component\Serializer\SerializerInterface;
17
18
final class ApiNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface
19
{
20
    private $decorated;
21
    private $imagineCacheManager;
22
    private $formViewFactory;
23
    private $pathResolver;
24
    private $em;
25
    private $projectDir;
26
27
    /**
28
     * FileNormalizer constructor.
29
     * @param NormalizerInterface $decorated
30
     * @param CacheManager $imagineCacheManager
31
     * @param FormViewFactory $formViewFactory
32
     * @param PathResolver $pathResolver
33
     * @param EntityManagerInterface $entityManager
34
     * @param string $projectDir
35
     */
36 10
    public function __construct(
37
        NormalizerInterface $decorated,
38
        CacheManager $imagineCacheManager,
39
        FormViewFactory $formViewFactory,
40
        PathResolver $pathResolver,
41
        EntityManagerInterface $entityManager,
42
        string $projectDir = '/'
43
    ) {
44 10
        if (!$decorated instanceof DenormalizerInterface) {
45
            throw new \InvalidArgumentException(sprintf('The decorated normalizer must implement the %s.', DenormalizerInterface::class));
46
        }
47 10
        $this->decorated = $decorated;
48 10
        $this->imagineCacheManager = $imagineCacheManager;
49 10
        $this->formViewFactory = $formViewFactory;
50 10
        $this->pathResolver = $pathResolver;
51 10
        $this->em = $entityManager;
52 10
        $this->projectDir = $projectDir;
53 10
    }
54
55
    /**
56
     * @param mixed $data
57
     * @param string|null $format
58
     * @return bool
59
     */
60 5
    public function supportsNormalization($data, $format = null): bool
61
    {
62 5
        return $this->decorated->supportsNormalization($data, $format);
63
    }
64
65
    /**
66
     * @param $object
67
     * @param string|null $format
68
     * @param array $context
69
     * @return array|bool|float|int|string
70
     * @throws \Symfony\Component\Serializer\Exception\LogicException
71
     * @throws \Symfony\Component\Serializer\Exception\InvalidArgumentException
72
     * @throws \Symfony\Component\Serializer\Exception\CircularReferenceException
73
     */
74 6
    public function normalize($object, $format = null, array $context = [])
75
    {
76 6
        if ($object instanceof Page) {
77
            if (!$object->getLayout()) {
78
                $object->setLayout($this->em->getRepository(Layout::class)->findOneBy(['default' => true]));
79
            }
80
        }
81 6
        if ($object instanceof Form && !$object->getForm()) {
82 1
            $object->setForm($this->formViewFactory->create($object));
83
        }
84 6
        $data = $this->decorated->normalize($object, $format, $context);
85
86 6
        if ($object instanceof FileInterface) {
87 1
            $data = array_merge($data, $this->getFileData($object));
88
        }
89 6
        return $data;
90
    }
91
92
    /**
93
     * @param \Silverback\ApiComponentBundle\Entity\Content\FileInterface $object
94
     * @return array
95
     */
96 1
    private function getFileData(FileInterface $object): array
97
    {
98 1
        $data = [];
99 1
        $filePath = $object->getFilePath();
100 1
        if ($filePath) {
101 1
            if (false !== \exif_imagetype($filePath)) {
102 1
                [$width, $height] = getimagesize($filePath);
103
            } else {
104
                $width = $height = 0;
105
            }
106 1
            $data['width'] = $width;
107 1
            $data['height'] = $height;
108
109 1
            $supported = $this->isImagineSupportedFile($filePath);
110 1
            foreach ($object::getImagineFilters() as $returnKey => $filter) {
111 1
                $data[$returnKey] = $supported ? parse_url(
112 1
                    $this->imagineCacheManager->getBrowserPath($this->pathResolver->resolve($filePath), $filter),
113 1
                    PHP_URL_PATH
114 1
                ) : null;
115
            }
116
117 1
            $data['filePath'] = $this->getPublicPath($filePath);
118
        }
119 1
        return $data;
120
    }
121
122 1
    private function getPublicPath(string $filePath) {
123 1
        $publicPaths = [$this->projectDir, '/public/', '/web/'];
124 1
        foreach ($publicPaths as $path) {
125 1
            if (mb_strpos($filePath, $path) === 0 && $start = \strlen($path)) {
126 1
                $filePath = mb_substr($filePath, $start);
127
            }
128
        }
129 1
        return $filePath;
130
    }
131
132
    /**
133
     * @param mixed $data
134
     * @param string $type
135
     * @param string|null $format
136
     * @return bool
137
     */
138 5
    public function supportsDenormalization($data, $type, $format = null): bool
139
    {
140 5
        return $this->decorated->supportsDenormalization($data, $type, $format);
141
    }
142
143
    /**
144
     * @param mixed $data
145
     * @param string $class
146
     * @param string|null $format
147
     * @param array $context
148
     * @return object
149
     * @throws \Symfony\Component\Serializer\Exception\UnexpectedValueException
150
     * @throws \Symfony\Component\Serializer\Exception\RuntimeException
151
     * @throws \Symfony\Component\Serializer\Exception\LogicException
152
     * @throws \Symfony\Component\Serializer\Exception\InvalidArgumentException
153
     * @throws \Symfony\Component\Serializer\Exception\ExtraAttributesException
154
     * @throws \Symfony\Component\Serializer\Exception\BadMethodCallException
155
     * @throws \InvalidArgumentException
156
     */
157 1
    public function denormalize($data, $class, $format = null, array $context = [])
158
    {
159 1
        $context['allow_extra_attributes'] = $class === Form::class;
160 1
        return $this->decorated->denormalize($data, $class, $format, $context);
161
    }
162
163
    /**
164
     * @param SerializerInterface $serializer
165
     */
166 5
    public function setSerializer(SerializerInterface $serializer)
167
    {
168 5
        if ($this->decorated instanceof SerializerAwareInterface) {
169 5
            $this->decorated->setSerializer($serializer);
170
        }
171 5
    }
172
173
    /**
174
     * @param string $filePath
175
     * @return bool
176
     */
177 3
    public function isImagineSupportedFile(?string $filePath): bool
178
    {
179 3
        if (!$filePath) {
180
            return false;
181
        }
182
        try {
183 3
            $imageType = \exif_imagetype($filePath);
184 1
        } catch (\Exception $e) {
185 1
            return false;
186
        }
187 3
        return \in_array($imageType, [IMAGETYPE_JPEG, IMAGETYPE_JPEG2000, IMAGETYPE_PNG, IMAGETYPE_GIF], true);
188
    }
189
}
190