10
10
*/
11
11
12
12
namespace Symfony \Component \Serializer \Instantiator ;
13
+
13
14
use Symfony \Component \PropertyInfo \PropertyListExtractorInterface ;
14
- use Symfony \Component \Serializer \Exception \LogicException ;
15
15
use Symfony \Component \Serializer \Exception \MissingConstructorArgumentsException ;
16
16
use Symfony \Component \Serializer \Exception \RuntimeException ;
17
- use Symfony \Component \Serializer \Mapping \ClassDiscriminatorResolverInterface ;
18
17
use Symfony \Component \Serializer \NameConverter \NameConverterInterface ;
19
- use Symfony \Component \Serializer \Normalizer \AbstractNormalizer ;
20
- use Symfony \Component \Serializer \Normalizer \DenormalizerInterface ;
18
+ use Symfony \Component \Serializer \Normalizer \AbstractObjectNormalizer ;
19
+ use Symfony \Component \Serializer \Normalizer \DenormalizerAwareInterface ;
20
+ use Symfony \Component \Serializer \Normalizer \DenormalizerAwareTrait ;
21
21
use Symfony \Component \Serializer \Normalizer \ObjectToPopulateTrait ;
22
- use Symfony \Component \Serializer \SerializerAwareInterface ;
23
- use Symfony \Component \Serializer \SerializerAwareTrait ;
24
22
25
23
/**
26
24
* @author Jérôme Desjardins <[email protected] >
27
25
*/
28
- class Instantiator implements InstantiatorInterface, SerializerAwareInterface
26
+ class Instantiator implements InstantiatorInterface, DenormalizerAwareInterface
29
27
{
28
+ public const DEFAULT_CONSTRUCTOR_ARGUMENTS = AbstractObjectNormalizer::DEFAULT_CONSTRUCTOR_ARGUMENTS ;
29
+
30
30
use ObjectToPopulateTrait;
31
- use SerializerAwareTrait ;
31
+ use DenormalizerAwareTrait ;
32
32
33
33
private $ classDiscriminatorResolver ;
34
34
private $ propertyListExtractor ;
35
35
private $ nameConverter ;
36
36
37
- public function __construct (ClassDiscriminatorResolverInterface $ classDiscriminatorResolver , PropertyListExtractorInterface $ propertyListExtractor , NameConverterInterface $ nameConverter )
37
+ public function __construct (PropertyListExtractorInterface $ propertyListExtractor = null , NameConverterInterface $ nameConverter = null )
38
38
{
39
- $ this ->classDiscriminatorResolver = $ classDiscriminatorResolver ;
40
39
$ this ->propertyListExtractor = $ propertyListExtractor ;
41
40
$ this ->nameConverter = $ nameConverter ;
42
41
}
43
42
43
+ /**
44
+ * {@inheritdoc}
45
+ */
44
46
public function instantiate (string $ class , $ data , $ format = null , array $ context = [])
45
47
{
46
- if ($ this ->classDiscriminatorResolver && $ mapping = $ this ->classDiscriminatorResolver ->getMappingForClass ($ class )) {
47
- if (!isset ($ data [$ mapping ->getTypeProperty ()])) {
48
- throw new RuntimeException (sprintf ('Type property "%s" not found for the abstract object "%s" ' , $ mapping ->getTypeProperty (), $ class ));
49
- }
50
-
51
- $ type = $ data [$ mapping ->getTypeProperty ()];
52
- if (null === ($ mappedClass = $ mapping ->getClassForType ($ type ))) {
53
- throw new RuntimeException (sprintf ('The type "%s" has no mapped class for the abstract object "%s" ' , $ type , $ class ));
54
- }
48
+ $ allowedAttributes = $ this ->propertyListExtractor ? $ this ->propertyListExtractor ->getProperties ($ class , $ context ) : null ;
49
+ $ reflectionClass = new \ReflectionClass ($ class );
50
+ $ constructor = $ reflectionClass ->getConstructor ();
55
51
56
- $ class = $ mappedClass ;
52
+ if (null === $ constructor ) {
53
+ return new $ class ();
57
54
}
58
55
59
- $ reflectionClass = new \ ReflectionClass ( $ class );
56
+ $ constructorParameters = $ constructor -> getParameters ( );
60
57
61
- if (null !== $ object = $ this ->extractObjectToPopulate ($ class , $ context , AbstractNormalizer::OBJECT_TO_POPULATE )) {
62
- unset($ context [AbstractNormalizer::OBJECT_TO_POPULATE ]);
58
+ $ params = [];
59
+ foreach ($ constructorParameters as $ constructorParameter ) {
60
+ $ paramName = $ constructorParameter ->name ;
61
+ $ key = $ this ->nameConverter ? $ this ->nameConverter ->normalize ($ paramName , $ class , $ format , $ context ) : $ paramName ;
62
+ $ allowed = null === $ allowedAttributes || \in_array ($ paramName , $ allowedAttributes , true );
63
63
64
- return $ object ;
65
- }
64
+ if ($ allowed && $ constructorParameter ->isVariadic () && \array_key_exists ($ key , $ data )) {
65
+ if (!\is_array ($ data [$ paramName ])) {
66
+ throw new RuntimeException (sprintf ('Cannot create an instance of %s from serialized data because the variadic parameter %s can only accept an array. ' , $ class , $ constructorParameter ->name ));
67
+ }
66
68
67
- $ defaultConstructionArgumentKey = $ context ['defaultConstructionArgumentKey ' ] ?? AbstractNormalizer::DEFAULT_CONSTRUCTOR_ARGUMENTS
68
- $ allowedAttributes = $ this ->propertyListExtractor ->getProperties ($ class , $ context );
69
- $ constructor = $ reflectionClass ->getConstructor ();
70
- if ($ constructor ) {
71
- $ constructorParameters = $ constructor ->getParameters ();
72
-
73
- $ params = [];
74
- foreach ($ constructorParameters as $ constructorParameter ) {
75
- $ paramName = $ constructorParameter ->name ;
76
- $ key = $ this ->nameConverter ? $ this ->nameConverter ->normalize ($ paramName , $ class , $ format , $ context ) : $ paramName ;
77
-
78
- $ allowed = false === $ allowedAttributes || \in_array ($ paramName , $ allowedAttributes );
79
- if ($ constructorParameter ->isVariadic ()) {
80
- if ($ allowed && (isset ($ data [$ key ]) || \array_key_exists ($ key , $ data ))) {
81
- if (!\is_array ($ data [$ paramName ])) {
82
- throw new RuntimeException (sprintf ('Cannot create an instance of %s from serialized data because the variadic parameter %s can only accept an array. ' , $ class , $ constructorParameter ->name ));
83
- }
84
-
85
- $ params = array_merge ($ params , $ data [$ paramName ]);
86
- }
87
- } elseif ($ allowed && (isset ($ data [$ key ]) || \array_key_exists ($ key , $ data ))) {
88
- $ parameterData = $ data [$ key ];
89
- if (null === $ parameterData && $ constructorParameter ->allowsNull ()) {
90
- $ params [] = null ;
91
- // Don't run set for a parameter passed to the constructor
92
- unset($ data [$ key ]);
93
- continue ;
94
- }
95
-
96
- // Don't run set for a parameter passed to the constructor
97
- $ params [] = $ this ->denormalizeParameter ($ reflectionClass , $ constructorParameter , $ paramName , $ parameterData , $ context , $ format );
98
- unset($ data [$ key ]);
99
- } elseif (\array_key_exists ($ key , $ context [$ defaultConstructionArgumentKey ][$ class ] ?? [])) {
100
- $ params [] = $ context [$ defaultConstructionArgumentKey ][$ class ][$ key ];
101
- } elseif ($ constructorParameter ->isDefaultValueAvailable ()) {
102
- $ params [] = $ constructorParameter ->getDefaultValue ();
103
- } else {
104
- throw new MissingConstructorArgumentsException (sprintf ('Cannot create an instance of %s from serialized data because its constructor requires parameter "%s" to be present. ' , $ class , $ constructorParameter ->name ));
69
+ $ params = array_merge ($ params , $ data [$ paramName ]);
70
+ } elseif ($ allowed && \array_key_exists ($ key , $ data )) {
71
+ $ parameterData = $ data [$ key ];
72
+
73
+ if (null === $ parameterData && $ constructorParameter ->allowsNull ()) {
74
+ $ params [] = null ;
75
+
76
+ continue ;
105
77
}
106
- }
107
78
108
- if ($ constructor ->isConstructor ()) {
109
- return $ reflectionClass ->newInstanceArgs ($ params );
79
+ $ params [] = $ this ->denormalizeParameter ($ reflectionClass , $ constructorParameter , $ paramName , $ parameterData , $ context , $ format );
80
+ } elseif (\array_key_exists ($ key , $ context [self ::DEFAULT_CONSTRUCTOR_ARGUMENTS ][$ class ] ?? [])) {
81
+ $ params [] = $ context [self ::DEFAULT_CONSTRUCTOR_ARGUMENTS ][$ class ][$ key ];
82
+ } elseif ($ constructorParameter ->isDefaultValueAvailable ()) {
83
+ $ params [] = $ constructorParameter ->getDefaultValue ();
84
+ } else {
85
+ throw new MissingConstructorArgumentsException (sprintf ('Cannot create an instance of %s from serialized data because its constructor requires parameter "%s" to be present. ' , $ class , $ constructorParameter ->name ));
110
86
}
111
-
112
- return $ constructor ->invokeArgs (null , $ params );
113
87
}
114
88
115
- return new $ class ();
116
- }
117
-
118
- public function createChildContext (string $ class , string $ attribute , $ parentData , array $ parentContext = [])
119
- {
120
- if (isset ($ parentContext [AbstractNormalizer::ATTRIBUTES ][$ attribute ])) {
121
- $ parentContext [AbstractNormalizer::ATTRIBUTES ] = $ parentContext [AbstractNormalizer::ATTRIBUTES ][$ attribute ];
122
- } else {
123
- unset($ parentContext [AbstractNormalizer::ATTRIBUTES ]);
89
+ if ($ constructor ->isConstructor ()) {
90
+ return $ reflectionClass ->newInstanceArgs ($ params );
124
91
}
125
92
126
- return $ parentContext ;
93
+ return $ constructor -> invokeArgs ( null , $ params ) ;
127
94
}
128
95
129
96
private function denormalizeParameter (\ReflectionClass $ class , \ReflectionParameter $ parameter , $ parameterName , $ parameterData , array $ context , $ format = null )
130
97
{
131
98
try {
132
99
if (null !== $ parameter ->getClass ()) {
133
- if (!$ this ->serializer instanceof DenormalizerInterface) {
134
- throw new LogicException (sprintf ('Cannot create an instance of %s from serialized data because the serializer inject in "%s" is not a denormalizer ' , $ parameter ->getClass (), self ::class));
135
- }
136
100
$ parameterClass = $ parameter ->getClass ()->getName ();
137
- $ parameterData = $ this ->serializer ->denormalize ($ parameterData , $ parameterClass , $ format , $ this ->createContext ($ context , $ parameterName ));
101
+
102
+ if (null === $ this ->denormalizer ) {
103
+ throw new MissingConstructorArgumentsException (sprintf ('Could not create object of class "%s" of the parameter "%s". ' , $ parameterClass , $ parameterName ));
104
+ }
105
+
106
+ $ parameterData = $ this ->denormalizer ->denormalize ($ parameterData , $ parameterClass , $ format , $ context );
138
107
}
139
108
} catch (\ReflectionException $ e ) {
140
109
throw new RuntimeException (sprintf ('Could not determine the class of the parameter "%s". ' , $ parameterName ), 0 , $ e );
@@ -147,5 +116,4 @@ private function denormalizeParameter(\ReflectionClass $class, \ReflectionParame
147
116
148
117
return $ parameterData ;
149
118
}
150
-
151
- }
119
+ }
0 commit comments