1313
1414use Symfony \Component \VarExporter \Exception \ExceptionInterface ;
1515use Symfony \Component \VarExporter \Exception \NotInstantiableTypeException ;
16- use Symfony \Component \VarExporter \Internal \Hydrator ;
1716use Symfony \Component \VarExporter \Internal \Registry ;
1817
1918/**
@@ -26,67 +25,35 @@ final class Instantiator
2625 /**
2726 * Creates an object and sets its properties without calling its constructor nor any other methods.
2827 *
29- * For example:
28+ * @see Hydrator::hydrate() for examples
3029 *
31- * // creates an empty instance of Foo
32- * Instantiator::instantiate(Foo::class);
30+ * @template T of object
3331 *
34- * // creates a Foo instance and sets one of its properties
35- * Instantiator::instantiate(Foo::class, ['propertyName' => $propertyValue]);
32+ * @param class-string<T> $class The class of the instance to create
33+ * @param array<string, mixed> $properties The properties to set on the instance
34+ * @param array<class-string, array<string, mixed>> $scopedProperties The properties to set on the instance,
35+ * keyed by their declaring class
3636 *
37- * // creates a Foo instance and sets a private property defined on its parent Bar class
38- * Instantiator::instantiate(Foo::class, [], [
39- * Bar::class => ['privateBarProperty' => $propertyValue],
40- * ]);
41- *
42- * Instances of ArrayObject, ArrayIterator and SplObjectHash can be created
43- * by using the special "\0" property name to define their internal value:
44- *
45- * // creates an SplObjectHash where $info1 is attached to $obj1, etc.
46- * Instantiator::instantiate(SplObjectStorage::class, ["\0" => [$obj1, $info1, $obj2, $info2...]]);
47- *
48- * // creates an ArrayObject populated with $inputArray
49- * Instantiator::instantiate(ArrayObject::class, ["\0" => [$inputArray]]);
50- *
51- * @param string $class The class of the instance to create
52- * @param array $properties The properties to set on the instance
53- * @param array $privateProperties The private properties to set on the instance,
54- * keyed by their declaring class
37+ * @return T
5538 *
5639 * @throws ExceptionInterface When the instance cannot be created
5740 */
58- public static function instantiate (string $ class , array $ properties = [], array $ privateProperties = []): object
41+ public static function instantiate (string $ class , array $ properties = [], array $ scopedProperties = []): object
5942 {
60- $ reflector = Registry::$ reflectors [$ class ] ?? Registry::getClassReflector ($ class );
43+ $ reflector = Registry::$ reflectors [$ class ] ??= Registry::getClassReflector ($ class );
6144
6245 if (Registry::$ cloneable [$ class ]) {
63- $ wrappedInstance = [ clone Registry::$ prototypes [$ class] ];
46+ $ instance = clone Registry::$ prototypes [$ class ];
6447 } elseif (Registry::$ instantiableWithoutConstructor [$ class ]) {
65- $ wrappedInstance = [ $ reflector ->newInstanceWithoutConstructor ()] ;
48+ $ instance = $ reflector ->newInstanceWithoutConstructor ();
6649 } elseif (null === Registry::$ prototypes [$ class ]) {
6750 throw new NotInstantiableTypeException ($ class );
6851 } elseif ($ reflector ->implementsInterface ('Serializable ' ) && !method_exists ($ class , '__unserialize ' )) {
69- $ wrappedInstance = [ unserialize ('C: ' .\strlen ($ class ).':" ' .$ class .'":0:{} ' )] ;
52+ $ instance = unserialize ('C: ' .\strlen ($ class ).':" ' .$ class .'":0:{} ' );
7053 } else {
71- $ wrappedInstance = [unserialize ('O: ' .\strlen ($ class ).':" ' .$ class .'":0:{} ' )];
72- }
73-
74- if ($ properties ) {
75- $ privateProperties [$ class ] = isset ($ privateProperties [$ class ]) ? $ properties + $ privateProperties [$ class ] : $ properties ;
76- }
77-
78- foreach ($ privateProperties as $ class => $ properties ) {
79- if (!$ properties ) {
80- continue ;
81- }
82- foreach ($ properties as $ name => $ value ) {
83- // because they're also used for "unserialization", hydrators
84- // deal with array of instances, so we need to wrap values
85- $ properties [$ name ] = [$ value ];
86- }
87- (Hydrator::$ hydrators [$ class ] ?? Hydrator::getHydrator ($ class ))($ properties , $ wrappedInstance );
54+ $ instance = unserialize ('O: ' .\strlen ($ class ).':" ' .$ class .'":0:{} ' );
8855 }
8956
90- return $ wrappedInstance [ 0 ] ;
57+ return Hydrator:: hydrate ( $ instance , $ properties , $ scopedProperties ) ;
9158 }
9259}
0 commit comments