Passed
Push — master ( 9ffd25...b7bf67 )
by Paweł
02:11
created

SerializerAdapter::canNormalize()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 3
nc 4
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Copyright (c) 2020.
4
 * @author Paweł Antosiak <[email protected]>
5
 */
6
7
declare(strict_types=1);
8
9
namespace Gorynych\Adapter;
10
11
use Gorynych\Exception\NotDeserializableException;
12
use Symfony\Component\Config\FileLocatorInterface;
13
use Symfony\Component\HttpFoundation\Request;
14
use Symfony\Component\Serializer\Encoder\EncoderInterface;
15
use Symfony\Component\Serializer\Encoder\JsonEncoder;
16
use Symfony\Component\Serializer\Encoder\XmlEncoder;
17
use Symfony\Component\Serializer\Exception\NotEncodableValueException;
18
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
19
use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader;
20
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
21
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
22
use Symfony\Component\Serializer\Serializer;
23
24
class SerializerAdapter
25
{
26
    protected Serializer $serializer;
27
    protected FileLocatorInterface $configLocator;
28
29
    public function __construct(FileLocatorInterface $configLocator)
30
    {
31
        $this->configLocator = $configLocator;
32
    }
33
34
    /**
35
     * Normalizes provided data
36
     *
37
     * @param object|object[] $data
38
     * @param mixed[] $context
39
     * @return mixed[]
40
     */
41
    public function normalize($data, array $context = []): array
42
    {
43
        return $this->serializer->normalize($data, null, $context);
44
    }
45
46
    /**
47
     * Deserializes input data into specified object
48
     *
49
     * @param string $data
50
     * @param string $outputClass
51
     * @param string $format
52
     * @param mixed[] $context
53
     * @return object
54
     *
55
     * @throws NotDeserializableException
56
     */
57
    public function deserialize(string $data, string $outputClass, string $format, array $context = []): object
58
    {
59
        try {
60
            return $this->serializer->deserialize($data, $outputClass, $format, $context);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->serializer...ass, $format, $context) could return the type array which is incompatible with the type-hinted return object. Consider adding an additional type-check to rule them out.
Loading history...
61
        } catch (NotEncodableValueException $e) {
62
            throw new NotDeserializableException($e->getMessage());
63
        }
64
    }
65
66
    /**
67
     * Returns TRUE is normalization for provided data representation can be processed
68
     *
69
     * @param mixed $data
70
     */
71
    public function canNormalize($data): bool
72
    {
73
        return (
74
            is_object($data) ||
75
            (is_array($data) && !empty($data) && is_object(current($data)))
76
        );
77
    }
78
79
    /**
80
     * Returns TRUE if deserialization for provided type can be processed
81
     */
82
    public function canDeserialize(string $type): bool
83
    {
84
        return Request::class !== $type && class_exists($type);
85
    }
86
87
    /**
88
     * Setups serializer
89
     *
90
     * @param string|null $definition Serializer definition name
91
     * @return self
92
     */
93
    public function setup(string $definition = null): self
94
    {
95
        if (false === empty($definition)) {
96
            $classMetadataFactory = new ClassMetadataFactory(new YamlFileLoader(
97
                $this->configLocator->locate("serializer/{$definition}.yaml")
0 ignored issues
show
Bug introduced by
It seems like $this->configLocator->lo.../'.$definition.'.yaml') can also be of type array; however, parameter $file of Symfony\Component\Serial...leLoader::__construct() 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

97
                /** @scrutinizer ignore-type */ $this->configLocator->locate("serializer/{$definition}.yaml")
Loading history...
98
            ));
99
        }
100
101
        $this->serializer = new Serializer(
102
            [new DateTimeNormalizer(), new ObjectNormalizer($classMetadataFactory ?? null)],
103
            $this->getEncoders()
104
        );
105
106
        return $this;
107
    }
108
109
    /**
110
     * @return EncoderInterface[]
111
     */
112
    protected function getEncoders(): array
113
    {
114
        return [new JsonEncoder(), new XmlEncoder()];
115
    }
116
}
117