Passed
Push — master ( c1f86b...00c5bd )
by Asmir
04:55 queued 02:40
created

SymfonyUidHandler::serializeUid()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 19
c 1
b 0
f 0
nc 9
nop 4
dl 0
loc 31
rs 8.8333
1
<?php
2
3
declare(strict_types=1);
4
5
namespace JMS\Serializer\Handler;
6
7
use JMS\Serializer\DeserializationContext;
8
use JMS\Serializer\Exception\InvalidArgumentException;
9
use JMS\Serializer\GraphNavigatorInterface;
10
use JMS\Serializer\SerializationContext;
11
use JMS\Serializer\Visitor\DeserializationVisitorInterface;
12
use JMS\Serializer\Visitor\SerializationVisitorInterface;
13
use JMS\Serializer\XmlSerializationVisitor;
14
use Symfony\Component\Uid\AbstractUid;
15
use Symfony\Component\Uid\Ulid;
16
use Symfony\Component\Uid\UuidV1;
17
use Symfony\Component\Uid\UuidV3;
18
use Symfony\Component\Uid\UuidV4;
19
use Symfony\Component\Uid\UuidV5;
20
use Symfony\Component\Uid\UuidV6;
21
22
final class SymfonyUidHandler implements SubscribingHandlerInterface
23
{
24
    public const FORMAT_BASE32    = 'base32';
25
    public const FORMAT_BASE58    = 'base58';
26
    public const FORMAT_CANONICAL = 'canonical';
27
    public const FORMAT_RFC4122   = 'rfc4122';
28
29
    private const UID_CLASSES = [
30
        Ulid::class,
31
        UuidV1::class,
32
        UuidV3::class,
33
        UuidV4::class,
34
        UuidV5::class,
35
        UuidV6::class,
36
    ];
37
38
    /**
39
     * @var string
40
     * @phpstan-var self::FORMAT_*
41
     */
42
    private $defaultFormat;
43
44
    /**
45
     * @var bool
46
     */
47
    private $xmlCData;
48
49
    public function __construct(string $defaultFormat = self::FORMAT_CANONICAL, bool $xmlCData = true)
50
    {
51
        $this->defaultFormat = $defaultFormat;
52
        $this->xmlCData = $xmlCData;
53
    }
54
55
    public static function getSubscribingMethods(): array
56
    {
57
        $methods = [];
58
        $formats = ['json', 'xml'];
59
60
        foreach ($formats as $format) {
61
            foreach (self::UID_CLASSES as $class) {
62
                $methods[] = [
63
                    'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
64
                    'format'    => $format,
65
                    'type'      => $class,
66
                    'method'    => 'serializeUid',
67
                ];
68
69
                $methods[] = [
70
                    'direction' => GraphNavigatorInterface::DIRECTION_DESERIALIZATION,
71
                    'format'    => $format,
72
                    'type'      => $class,
73
                    'method'    => 'deserializeUidFrom' . ucfirst($format),
74
                ];
75
            }
76
        }
77
78
        return $methods;
79
    }
80
81
    /**
82
     * @phpstan-param array{name: class-string<AbstractUid>, params: array} $type
83
     */
84
    public function deserializeUidFromJson(DeserializationVisitorInterface $visitor, ?string $data, array $type, DeserializationContext $context): ?AbstractUid
0 ignored issues
show
Unused Code introduced by
The parameter $visitor is not used and could be removed. ( Ignorable by Annotation )

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

84
    public function deserializeUidFromJson(/** @scrutinizer ignore-unused */ DeserializationVisitorInterface $visitor, ?string $data, array $type, DeserializationContext $context): ?AbstractUid

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $context is not used and could be removed. ( Ignorable by Annotation )

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

84
    public function deserializeUidFromJson(DeserializationVisitorInterface $visitor, ?string $data, array $type, /** @scrutinizer ignore-unused */ DeserializationContext $context): ?AbstractUid

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
85
    {
86
        if (null === $data) {
87
            return null;
88
        }
89
90
        return $this->deserializeUid($data, $type);
91
    }
92
93
    /**
94
     * @phpstan-param array{name: class-string<AbstractUid>, params: array} $type
95
     */
96
    public function deserializeUidFromXml(DeserializationVisitorInterface $visitor, \SimpleXMLElement $data, array $type, DeserializationContext $context): ?AbstractUid
0 ignored issues
show
Unused Code introduced by
The parameter $visitor is not used and could be removed. ( Ignorable by Annotation )

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

96
    public function deserializeUidFromXml(/** @scrutinizer ignore-unused */ DeserializationVisitorInterface $visitor, \SimpleXMLElement $data, array $type, DeserializationContext $context): ?AbstractUid

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $context is not used and could be removed. ( Ignorable by Annotation )

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

96
    public function deserializeUidFromXml(DeserializationVisitorInterface $visitor, \SimpleXMLElement $data, array $type, /** @scrutinizer ignore-unused */ DeserializationContext $context): ?AbstractUid

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
97
    {
98
        if ($this->isDataXmlNull($data)) {
99
            return null;
100
        }
101
102
        return $this->deserializeUid((string) $data, $type);
103
    }
104
105
    /**
106
     * @phpstan-param array{name: class-string<AbstractUid>, params: array} $type
107
     */
108
    private function deserializeUid(string $data, array $type): ?AbstractUid
109
    {
110
        /** @var class-string<AbstractUid> $uidClass */
111
        $uidClass = $type['name'];
112
113
        try {
114
            return $uidClass::fromString($data);
115
        } catch (\InvalidArgumentException | \TypeError $exception) {
116
            throw new InvalidArgumentException(sprintf('"%s" is not a valid UID string.', $data), 0, $exception);
117
        }
118
    }
119
120
    /**
121
     * @return \DOMText|string
122
     *
123
     * @phpstan-param array{name: class-string<AbstractUid>, params: array} $type
124
     */
125
    public function serializeUid(SerializationVisitorInterface $visitor, AbstractUid $uid, array $type, SerializationContext $context)
0 ignored issues
show
Unused Code introduced by
The parameter $context is not used and could be removed. ( Ignorable by Annotation )

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

125
    public function serializeUid(SerializationVisitorInterface $visitor, AbstractUid $uid, array $type, /** @scrutinizer ignore-unused */ SerializationContext $context)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
126
    {
127
        /** @phpstan-var self::FORMAT_* $format */
128
        $format = $type['params'][0]['name'] ?? $this->defaultFormat;
129
130
        switch ($format) {
131
            case self::FORMAT_BASE32:
132
                $serialized = $uid->toBase32();
133
                break;
134
135
            case self::FORMAT_BASE58:
136
                $serialized = $uid->toBase58();
137
                break;
138
139
            case self::FORMAT_CANONICAL:
140
                $serialized = (string) $uid;
141
                break;
142
143
            case self::FORMAT_RFC4122:
144
                $serialized = $uid->toRfc4122();
145
                break;
146
147
            default:
148
                throw new InvalidArgumentException(sprintf('The "%s" format is not valid.', $format));
149
        }
150
151
        if ($visitor instanceof XmlSerializationVisitor && false === $this->xmlCData) {
152
            return $visitor->visitSimpleString($serialized, $type);
153
        }
154
155
        return $visitor->visitString($serialized, $type);
156
    }
157
158
    /**
159
     * @param mixed $data
160
     */
161
    private function isDataXmlNull($data): bool
162
    {
163
        $attributes = $data->attributes('xsi', true);
164
165
        return isset($attributes['nil'][0]) && 'true' === (string) $attributes['nil'][0];
166
    }
167
}
168