1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Fitbug\SymfonySerializer\YamlEncoderDecoder; |
4
|
|
|
|
5
|
|
|
use Symfony\Component\Serializer\Encoder\DecoderInterface; |
6
|
|
|
use Symfony\Component\Serializer\Exception\UnexpectedValueException; |
7
|
|
|
use Symfony\Component\Yaml\Yaml; |
8
|
|
|
|
9
|
|
|
class YamlDecode implements DecoderInterface |
10
|
|
|
{ |
11
|
|
|
const OPTION_EXCEPTION_ON_INVALID_TYPE = 'yaml_decode_exception_on_invalid_type'; |
12
|
|
|
const OPTION_OBJECT = 'yaml_decode_object'; |
13
|
|
|
const OPTION_OBJECT_FOR_MAP = 'yaml_decode_object_for_map'; |
14
|
|
|
const OPTION_DATE_TIME = 'yaml_decode_date_time'; |
15
|
|
|
const SUPPORTED_ENCODING_YAML = "yaml"; |
16
|
|
|
/** |
17
|
|
|
* @var bool |
18
|
|
|
*/ |
19
|
|
|
private $exceptionOnInvalidType; |
20
|
|
|
/** |
21
|
|
|
* @var bool |
22
|
|
|
*/ |
23
|
|
|
private $object; |
24
|
|
|
/** |
25
|
|
|
* @var bool |
26
|
|
|
*/ |
27
|
|
|
private $objectForMap; |
28
|
|
|
/** |
29
|
|
|
* @var bool |
30
|
|
|
*/ |
31
|
|
|
private $dateTime; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Constructs a new YamlDecode instance. |
35
|
|
|
* |
36
|
|
|
* @param bool $exceptionOnInvalidType |
37
|
|
|
* @param bool $object |
38
|
|
|
* @param bool $objectForMap |
39
|
|
|
* @param bool $dateTime |
40
|
|
|
*/ |
41
|
|
|
public function __construct( |
42
|
|
|
$exceptionOnInvalidType = false, |
43
|
|
|
$object = false, |
44
|
|
|
$objectForMap = false, |
45
|
|
|
$dateTime = false |
46
|
|
|
) { |
47
|
|
|
$this->exceptionOnInvalidType = $exceptionOnInvalidType; |
48
|
|
|
$this->object = $object; |
49
|
|
|
$this->objectForMap = $objectForMap; |
50
|
|
|
$this->dateTime = $dateTime; |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Decodes a string into PHP data. |
55
|
|
|
* |
56
|
|
|
* @param string $data Data to decode |
57
|
|
|
* @param string $format Format name |
58
|
|
|
* @param array $context options that decoders have access to |
59
|
|
|
* |
60
|
|
|
* The format parameter specifies which format the data is in; valid values |
61
|
|
|
* depend on the specific implementation. The only format we support is 'yaml' |
62
|
|
|
* |
63
|
|
|
* @return mixed |
64
|
|
|
* |
65
|
|
|
* @throws UnexpectedValueException |
66
|
|
|
*/ |
67
|
|
|
public function decode($data, $format, array $context = []) |
68
|
|
|
{ |
69
|
|
|
$context = $this->resolveContext($context); |
70
|
|
|
|
71
|
|
|
if ($this->isYamlOldStyleInterface()) { |
72
|
|
|
$results = Yaml::parse( |
73
|
|
|
$data, |
74
|
|
|
$context[ self::OPTION_EXCEPTION_ON_INVALID_TYPE ], |
75
|
|
|
$context[ self::OPTION_OBJECT ], |
76
|
|
|
$context[ self::OPTION_OBJECT_FOR_MAP ] |
77
|
|
|
); |
78
|
|
|
} else { |
79
|
|
|
$options = $this->contextToOptions($context); |
80
|
|
|
|
81
|
|
|
$results = Yaml::parse($data, $options); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
return $results; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Checks whether the deserializer can decode from given format. |
89
|
|
|
* |
90
|
|
|
* We only support yaml. |
91
|
|
|
* |
92
|
|
|
* @param string $format format name |
93
|
|
|
* |
94
|
|
|
* @return bool |
95
|
|
|
*/ |
96
|
|
|
public function supportsDecoding($format) |
97
|
|
|
{ |
98
|
|
|
return $format == self::SUPPORTED_ENCODING_YAML; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* Merges the default options of the Yaml Decoder with the passed context. |
103
|
|
|
* |
104
|
|
|
* @param array $context |
105
|
|
|
* |
106
|
|
|
* @return array |
107
|
|
|
*/ |
108
|
|
|
private function resolveContext(array $context) |
109
|
|
|
{ |
110
|
|
|
$defaultOptions = [ |
111
|
|
|
self::OPTION_EXCEPTION_ON_INVALID_TYPE => $this->exceptionOnInvalidType, |
112
|
|
|
self::OPTION_OBJECT => $this->object, |
113
|
|
|
self::OPTION_OBJECT_FOR_MAP => $this->objectForMap, |
114
|
|
|
self::OPTION_DATE_TIME => $this->dateTime, |
115
|
|
|
]; |
116
|
|
|
|
117
|
|
|
return array_merge($defaultOptions, $context); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* Convert the context to options understood by the parser |
122
|
|
|
* |
123
|
|
|
* @param array $options |
124
|
|
|
* |
125
|
|
|
* @return int |
126
|
|
|
*/ |
127
|
|
View Code Duplication |
private function contextToOptions(array $options) |
|
|
|
|
128
|
|
|
{ |
129
|
|
|
$optionToBitMap = [ |
130
|
|
|
self::OPTION_EXCEPTION_ON_INVALID_TYPE => Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE, |
131
|
|
|
self::OPTION_OBJECT => Yaml::PARSE_OBJECT, |
132
|
|
|
self::OPTION_OBJECT_FOR_MAP => Yaml::PARSE_OBJECT_FOR_MAP, |
133
|
|
|
self::OPTION_DATE_TIME => Yaml::PARSE_DATETIME, |
134
|
|
|
]; |
135
|
|
|
|
136
|
|
|
$bitMaskedOption = 0; |
137
|
|
|
|
138
|
|
|
foreach ($optionToBitMap as $option => $bitMask) { |
139
|
|
|
if ($options[ $option ]) { |
140
|
|
|
$bitMaskedOption = $bitMaskedOption | $bitMask; |
141
|
|
|
} |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
return $bitMaskedOption; |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
private function isYamlOldStyleInterface() |
148
|
|
|
{ |
149
|
|
|
return !defined("Symfony\\Component\\Yaml\\Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE"); |
150
|
|
|
} |
151
|
|
|
} |
152
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.