@@ -19,57 +19,52 @@ class ObjectGraphGenerator
19
19
{
20
20
private const DEFAULT_SEED = 1 ;
21
21
22
- /** @var Generator */
23
- private $ fakerInstance ;
24
-
25
- /** @var PropertyInfoExtractor */
26
- private $ propertyInfo ;
27
-
28
- /** @var array */
29
- private $ registry ;
22
+ private Generator $ fakerInstance ;
23
+ private PropertyInfoExtractor $ propertyInfo ;
24
+ /**
25
+ * @var array<mixed>
26
+ */
27
+ private array $ registry ;
30
28
31
- /** @var array */
32
- private $ temporaryRegistry = [];
29
+ /**
30
+ * @var array<mixed>
31
+ */
32
+ private array $ temporaryRegistry = [];
33
33
34
+ /**
35
+ * @param array<mixed> $registry
36
+ */
34
37
public function __construct (array $ registry = [])
35
38
{
36
39
$ this ->fakerInstance = Factory::create ();
37
40
38
- $ phpDocExtractor = new PhpDocExtractor ();
41
+ $ phpDocExtractor = new PhpDocExtractor ();
39
42
$ reflectionExtractor = new ReflectionExtractor ();
40
- $ typeExtractors = [$ phpDocExtractor , $ reflectionExtractor ];
41
- $ this ->propertyInfo = new PropertyInfoExtractor ([], $ typeExtractors , [], [], []);
43
+ $ typeExtractors = [$ phpDocExtractor , $ reflectionExtractor ];
44
+ $ this ->propertyInfo = new PropertyInfoExtractor ([], $ typeExtractors , [], [], []);
42
45
$ this ->fakerInstance ->seed (self ::DEFAULT_SEED );
43
46
$ this ->registry = $ registry ;
44
47
}
45
48
49
+ /**
50
+ * @param class-string $className
51
+ */
46
52
public function generate (string $ className ): object
47
53
{
48
54
return $ this ->generateObject ($ className );
49
55
}
50
56
51
- public function generateWithTemporaryConfig (string $ className , array $ config ): object
52
- {
53
- $ this ->temporaryRegistry = $ config ;
54
- $ object = $ this ->generateObject ($ className );
55
- $ this ->temporaryRegistry = [];
56
-
57
- return $ object ;
58
- }
59
-
60
57
/**
61
- * @param string $className
62
- *
63
- * @return mixed|object
58
+ * @param class-string $className
64
59
* @throws ReflectionException
65
60
*/
66
- private function generateObject (string $ className )
61
+ private function generateObject (string $ className ): object
67
62
{
68
63
if ($ this ->isInRegistry ($ className )) {
69
64
return $ this ->getFromRegistry ($ className );
70
65
}
71
66
72
- $ class = new ReflectionClass ($ className );
67
+ $ class = new ReflectionClass ($ className );
73
68
$ factoryMethod = $ this ->findFactoryMethod ($ class );
74
69
75
70
if ($ factoryMethod === null ) {
@@ -78,6 +73,7 @@ private function generateObject(string $className)
78
73
79
74
$ arguments = array_map (
80
75
function (ReflectionParameter $ parameter ) use ($ className ) {
76
+ /** @var array<mixed> $type */
81
77
$ type = $ this ->propertyInfo ->getTypes ($ className , $ parameter ->getName ());
82
78
83
79
return $ this ->generateArgument ($ type [0 ], $ className , $ parameter ->getName ());
@@ -90,13 +86,34 @@ function (ReflectionParameter $parameter) use ($className) {
90
86
: $ factoryMethod ->invokeArgs (null , $ arguments );
91
87
}
92
88
89
+ private function isInRegistry (string $ key ): bool
90
+ {
91
+ return array_key_exists ($ key , $ this ->temporaryRegistry ) || array_key_exists ($ key , $ this ->registry );
92
+ }
93
+
94
+ /**
95
+ * @return mixed
96
+ */
97
+ private function getFromRegistry (string $ key )
98
+ {
99
+ if (isset ($ this ->temporaryRegistry [$ key ])) {
100
+ return $ this ->temporaryRegistry [$ key ]($ this , $ this ->fakerInstance );
101
+ }
102
+
103
+ return $ this ->registry [$ key ]($ this , $ this ->fakerInstance );
104
+ }
105
+
106
+ /**
107
+ * @param ReflectionClass<object> $class
108
+ */
93
109
private function findFactoryMethod (ReflectionClass $ class ): ?ReflectionMethod
94
110
{
95
111
try {
96
112
return $ class ->getMethod ('createNew ' );
97
113
} catch (ReflectionException $ e ) {
98
114
// Do nothing here
99
115
}
116
+
100
117
try {
101
118
return $ class ->getMethod ('create ' );
102
119
} catch (ReflectionException $ e ) {
@@ -105,60 +122,70 @@ private function findFactoryMethod(ReflectionClass $class): ?ReflectionMethod
105
122
}
106
123
107
124
/**
108
- * @param Type $type
109
- *
110
- * @param string $className
111
- * @param string $argumentName
112
- *
113
125
* @return mixed
114
126
* @throws ReflectionException
115
127
*/
116
128
private function generateArgument (Type $ type , string $ className , string $ argumentName )
117
129
{
118
130
$ faker = $ type ->isNullable () ? $ this ->fakerInstance ->optional () : $ this ->fakerInstance ;
119
131
$ key = sprintf ('%s:%s ' , $ className , $ argumentName );
132
+
120
133
if ($ this ->isInRegistry ($ key )) {
121
134
return $ this ->getFromRegistry ($ key );
122
135
}
123
136
124
137
switch ($ type ->getBuiltinType ()) {
125
138
case Type::BUILTIN_TYPE_INT :
126
139
return $ faker ->randomNumber (5 );
140
+
127
141
case Type::BUILTIN_TYPE_FLOAT :
128
142
return $ faker ->randomFloat ();
143
+
129
144
case Type::BUILTIN_TYPE_STRING :
130
145
return $ faker ->text (100 );
146
+
131
147
case Type::BUILTIN_TYPE_BOOL :
132
148
return $ faker ->boolean ();
149
+
133
150
case Type::BUILTIN_TYPE_ARRAY :
134
151
$ collection = [];
152
+
135
153
if ($ type ->isCollection ()) {
136
154
$ collection = array_map (
137
155
function () use ($ argumentName , $ className , $ type ) {
138
- return $ this ->generateArgument ($ type ->getCollectionValueType (), $ className , $ argumentName );
156
+ /** @var Type $collectionValueType */
157
+ $ collectionValueType = $ type ->getCollectionValueType ();
158
+
159
+ return $ this ->generateArgument ($ collectionValueType , $ className , $ argumentName );
139
160
},
140
161
range (0 , $ faker ->numberBetween (0 , 10 ))
141
162
);
142
163
}
164
+
143
165
return $ faker ->passthrough ($ collection );
166
+
144
167
case Type::BUILTIN_TYPE_OBJECT :
145
- if ($ type ->getClassName () === 'DateTime ' ) {
168
+ /** @var class-string $className */
169
+ $ className = $ type ->getClassName ();
170
+
171
+ if ($ className === 'DateTime ' ) {
146
172
return $ faker ->dateTime ();
147
173
}
148
- return $ faker ->passthrough ($ this ->generateObject ($ type ->getClassName ()));
174
+
175
+ return $ faker ->passthrough ($ this ->generateObject ($ className ));
149
176
}
150
177
}
151
178
152
- private function isInRegistry (string $ key ): bool
179
+ /**
180
+ * @param class-string $className
181
+ * @param array<mixed> $config
182
+ */
183
+ public function generateWithTemporaryConfig (string $ className , array $ config ): object
153
184
{
154
- return array_key_exists ($ key , $ this ->temporaryRegistry ) || array_key_exists ($ key , $ this ->registry );
155
- }
185
+ $ this ->temporaryRegistry = $ config ;
186
+ $ object = $ this ->generateObject ($ className );
187
+ $ this ->temporaryRegistry = [];
156
188
157
- private function getFromRegistry (string $ key )
158
- {
159
- if (isset ($ this ->temporaryRegistry [$ key ])) {
160
- return $ this ->temporaryRegistry [$ key ]($ this , $ this ->fakerInstance );
161
- }
162
- return $ this ->registry [$ key ]($ this , $ this ->fakerInstance );
189
+ return $ object ;
163
190
}
164
191
}
0 commit comments