@@ -48,10 +48,11 @@ public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount
48
48
$ refs [$ k ] = $ value = $ values [$ k ];
49
49
if ($ value instanceof Reference && 0 > $ value ->id ) {
50
50
$ valuesAreStatic = false ;
51
+ ++$ value ->count ;
51
52
continue ;
52
53
}
53
54
$ refsPool [] = array (&$ refs [$ k ], $ value , &$ value );
54
- $ refs [$ k ] = $ values [$ k ] = new Reference (-\count ($ refsPool ));
55
+ $ refs [$ k ] = $ values [$ k ] = new Reference (-\count ($ refsPool ), $ value );
55
56
}
56
57
57
58
if (\is_array ($ value )) {
@@ -80,12 +81,13 @@ public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount
80
81
Registry::getClassReflector ($ class );
81
82
serialize (Registry::$ prototypes [$ class ]);
82
83
}
84
+ $ reflector = Registry::$ reflectors [$ class ];
83
85
$ proto = Registry::$ prototypes [$ class ];
84
86
85
87
if ($ value instanceof \ArrayIterator || $ value instanceof \ArrayObject) {
86
88
// ArrayIterator and ArrayObject need special care because their "flags"
87
89
// option changes the behavior of the (array) casting operator.
88
- $ proto = Registry::$ cloneable [$ class ] ? clone Registry::$ prototypes [$ class ] : Registry:: $ reflectors [ $ class ] ->newInstanceWithoutConstructor ();
90
+ $ proto = Registry::$ cloneable [$ class ] ? clone Registry::$ prototypes [$ class ] : $ reflector ->newInstanceWithoutConstructor ();
89
91
$ properties = self ::getArrayObjectProperties ($ value , $ arrayValue , $ proto );
90
92
} elseif ($ value instanceof \SplObjectStorage) {
91
93
// By implementing Serializable, SplObjectStorage breaks internal references,
@@ -116,20 +118,29 @@ public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount
116
118
foreach ($ arrayValue as $ name => $ v ) {
117
119
$ n = (string ) $ name ;
118
120
if ('' === $ n || "\0" !== $ n [0 ]) {
119
- $ c = $ class ;
121
+ $ c = '* ' ;
122
+ $ properties [$ c ][$ n ] = $ v ;
123
+ unset($ sleep [$ n ]);
120
124
} elseif ('* ' === $ n [1 ]) {
121
- $ c = $ class ;
122
125
$ n = substr ($ n , 3 );
126
+ $ c = $ reflector ->getProperty ($ n )->class ;
127
+ if ('Error ' === $ c ) {
128
+ $ c = 'TypeError ' ;
129
+ } elseif ('Exception ' === $ c ) {
130
+ $ c = 'ErrorException ' ;
131
+ }
132
+ $ properties [$ c ][$ n ] = $ v ;
133
+ unset($ sleep [$ n ]);
123
134
} else {
124
135
$ i = strpos ($ n , "\0" , 2 );
125
136
$ c = substr ($ n , 1 , $ i - 1 );
126
137
$ n = substr ($ n , 1 + $ i );
127
- }
128
- if ( null === $ sleep ) {
129
- $ properties [ $ c ][ $ n ] = $ v ;
130
- } elseif ( isset ( $ sleep [ $ n ]) && $ c === $ class ) {
131
- $ properties [ $ c ][ $ n ] = $ v ;
132
- unset( $ sleep [ $ n ]);
138
+ if ( null === $ sleep ) {
139
+ $ properties [ $ c ][ $ n ] = $ v ;
140
+ } elseif ( isset ( $ sleep [ $ n ]) && $ c === $ class ) {
141
+ $ properties [ $ c ][ $ n ] = $ v ;
142
+ unset( $ sleep [ $ n ]) ;
143
+ }
133
144
}
134
145
if (\array_key_exists ($ name , $ proto ) && $ proto [$ name ] === $ v ) {
135
146
unset($ properties [$ c ][$ n ]);
@@ -173,11 +184,14 @@ public static function export($value, $indent = '')
173
184
174
185
if ($ value instanceof Reference) {
175
186
if (0 <= $ value ->id ) {
176
- return '\\' .Registry::class.'::$objects[ ' .$ value ->id .'] ' ;
187
+ return '$o[ ' .$ value ->id .'] ' ;
188
+ }
189
+ if (!$ value ->count ) {
190
+ return self ::export ($ value ->value , $ indent );
177
191
}
178
192
$ value = -$ value ->id ;
179
193
180
- return '& \\' .Registry::class. ' ::$references [ ' .$ value .'] ' ;
194
+ return '&$r [ ' .$ value .'] ' ;
181
195
}
182
196
$ subIndent = $ indent .' ' ;
183
197
@@ -224,9 +238,9 @@ public static function export($value, $indent = '')
224
238
}
225
239
226
240
if ($ value instanceof Values) {
227
- $ code = '' ;
241
+ $ code = $ subIndent . "\$ r = [], \n" ;
228
242
foreach ($ value ->values as $ k => $ v ) {
229
- $ code .= $ subIndent .'\\' .Registry::class. ' ::$references [ ' .$ k .'] = ' .self ::export ($ v , $ subIndent ).", \n" ;
243
+ $ code .= $ subIndent .'$r [ ' .$ k .'] = ' .self ::export ($ v , $ subIndent ).", \n" ;
230
244
}
231
245
232
246
return "[ \n" .$ code .$ indent .'] ' ;
@@ -236,42 +250,64 @@ public static function export($value, $indent = '')
236
250
$ code = '' ;
237
251
$ reflectors = array ();
238
252
$ serializables = array ();
253
+ $ seen = array ();
254
+ $ prototypesAccess = 0 ;
255
+ $ factoriesAccess = 0 ;
256
+ $ r = '\\' .Registry::class;
239
257
240
258
foreach ($ value as $ k => $ class ) {
241
259
if (': ' === ($ class [1 ] ?? null )) {
242
260
$ serializables [$ k ] = $ class ;
243
261
continue ;
244
262
}
245
- $ c = '\\' .$ class .'::class ' ;
246
- $ reflectors [$ class ] = '\\' .Registry::class.'::$reflectors[ ' .$ c .'] ?? \\' .Registry::class.'::getClassReflector( ' .$ c .', '
247
- .self ::export (Registry::$ instantiableWithoutConstructor [$ class ]).', '
248
- .self ::export (Registry::$ cloneable [$ class ])
249
- .') ' ;
250
-
251
- if (Registry::$ cloneable [$ class ]) {
252
- $ code .= $ subIndent .'clone \\' .Registry::class.'::$prototypes[ ' .$ c ."], \n" ;
253
- } elseif (Registry::$ instantiableWithoutConstructor [$ class ]) {
254
- $ code .= $ subIndent .'\\' .Registry::class.'::$reflectors[ ' .$ c ."]->newInstanceWithoutConstructor(), \n" ;
263
+ $ code .= $ subIndent .$ k .' => ' ;
264
+
265
+ $ c = '[ \\' .$ class .'::class] ' ;
266
+ if ($ seen [$ class ] ?? false ) {
267
+ if (Registry::$ cloneable [$ class ]) {
268
+ ++$ prototypesAccess ;
269
+ $ code .= 'clone $p ' .$ c .", \n" ;
270
+ } else {
271
+ ++$ factoriesAccess ;
272
+ $ code .= '$f ' .$ c ."(), \n" ;
273
+ }
255
274
} else {
256
- $ code .= $ subIndent .'\\' .Registry::class.'::$reflectors[ ' .$ c ."]->newInstance(), \n" ;
275
+ $ seen [$ class ] = true ;
276
+ $ k = '( ' .substr ($ c , 1 , -1 ).', ' .self ::export (Registry::$ instantiableWithoutConstructor [$ class ]).')) ';
277
+
278
+ if (Registry::$ cloneable [$ class ]) {
279
+ $ code .= 'clone ( ' .($ prototypesAccess ++ ? '$p ' : '($p =& ' .$ r .'::$prototypes) ' ).$ c .' ?? ' .$ r .'::p ' .$ k .", \n" ;
280
+ } else {
281
+ $ code .= '( ' .($ factoriesAccess ++ ? '$f ' : '($f =& ' .$ r .'::$factories) ' ).$ c .' ?? ' .$ r .'::f ' .$ k ."(), \n" ;
282
+ }
257
283
}
258
284
}
259
285
260
- if ($ reflectors ) {
261
- $ code = "[ \n" .$ subIndent .implode (", \n" .$ subIndent , $ reflectors ).", \n" .$ indent ."], [ \n" .$ code .$ indent .'], ' ;
262
- $ code .= !$ serializables ? "[ \n" .$ indent .'] ' : self ::export ($ serializables , $ indent );
286
+ if (1 === $ prototypesAccess ) {
287
+ $ code = str_replace ('($p =& ' .$ r .'::$prototypes) ' , $ r .'::$prototypes ' , $ code );
288
+ }
289
+ if (1 === $ factoriesAccess ) {
290
+ $ code = str_replace ('($f =& ' .$ r .'::$factories) ' , $ r .'::$factories ' , $ code );
291
+ }
292
+
293
+ if ('' !== $ code ) {
294
+ $ code = "\n" .$ code .$ indent ;
295
+ }
296
+
297
+ if ($ serializables ) {
298
+ $ code = $ r .'::unserialize([ ' .$ code .'], ' .self ::export ($ serializables , $ indent ).') ' ;
263
299
} else {
264
- $ code = '[], [] ' ;
265
- $ code .= ', ' .self ::export ($ serializables , $ indent );
300
+ $ code = '[ ' .$ code .'] ' ;
266
301
}
267
302
268
- return '\\' .Registry::class. ' ::push( ' . $ code. ' ) ' ;
303
+ return '$o = ' . $ code ;
269
304
}
270
305
271
306
if ($ value instanceof Configurator) {
272
307
$ code = '' ;
273
308
foreach ($ value ->properties as $ class => $ properties ) {
274
- $ code .= $ subIndent .' \\' .$ class .'::class => ' .self ::export ($ properties , $ subIndent .' ' ).", \n" ;
309
+ $ c = '* ' !== $ class ? '\\' .$ class .'::class ' : "'*' " ;
310
+ $ code .= $ subIndent .' ' .$ c .' => ' .self ::export ($ properties , $ subIndent .' ' ).", \n" ;
275
311
}
276
312
277
313
$ code = array (
0 commit comments