@@ -342,10 +342,137 @@ public static function reverseRoundtripProvider(): iterable
342342 $ outer ->child = $ inner ;
343343 yield [$ outer , 'nested object ' ];
344344
345- // Array with objects (falls back to dump )
345+ // Array with objects (bails to VarCloner )
346346 $ obj = new \stdClass ();
347347 $ obj ->id = 1 ;
348348 yield [['item ' => $ obj ], 'array with object ' ];
349+ }
350+
351+ // ── Additional coverage ──────────────────────────────────────────
352+
353+ public function testArrayWithObjectBailsToVarCloner (): void
354+ {
355+ $ d = new JsonDataFormatter ();
356+ $ obj = new \stdClass ();
357+ $ obj ->x = 1 ;
358+
359+ // Object at first position — bails immediately
360+ $ data = $ d ->formatVar ([$ obj , 'plain ' ]);
361+ $ this ->assertIsArray ($ data );
362+ $ this ->assertArrayHasKey ('_vd ' , $ data [0 ]);
363+ }
364+
365+ public function testArrayWithObjectAtEnd (): void
366+ {
367+ $ d = new JsonDataFormatter ();
368+ $ obj = new \stdClass ();
369+ $ obj ->x = 1 ;
370+
371+ // Object at last position — iterates scalars first, then bails
372+ $ data = $ d ->formatVar (['a ' => 1 , 'b ' => 'two ' , 'obj ' => $ obj ]);
373+ $ this ->assertIsArray ($ data );
374+ $ this ->assertArrayHasKey ('_vd ' , $ data ['obj ' ]);
375+ }
376+
377+ public function testNestedArrayWithObjectAtLevel2 (): void
378+ {
379+ $ d = new JsonDataFormatter ();
380+ $ obj = new \stdClass ();
381+ $ obj ->name = 'deep ' ;
382+
383+ // Object nested 2 levels deep — bail bubbles up
384+ $ data = $ d ->formatVar (['users ' => ['first ' => $ obj , 'count ' => 1 ]]);
385+ $ this ->assertIsArray ($ data );
386+ // The entire thing went through VarCloner
387+ $ this ->assertArrayHasKey ('_vd ' , $ data ['users ' ]['first ' ]);
388+ }
389+
390+ public function testNestedArrayWithObjectAtLevel3 (): void
391+ {
392+ $ d = new JsonDataFormatter ();
393+ $ obj = new \stdClass ();
394+ $ obj ->id = 42 ;
395+
396+ $ data = $ d ->formatVar (['level1 ' => ['level2 ' => ['obj ' => $ obj , 'n ' => 1 ]]]);
397+ $ this ->assertIsArray ($ data );
398+ $ this ->assertArrayHasKey ('_vd ' , $ data ['level1 ' ]['level2 ' ]['obj ' ]);
399+ }
400+
401+ public function testMixedArrayScalarsAndNestedArrays (): void
402+ {
403+ $ d = new JsonDataFormatter ();
404+
405+ $ data = $ d ->formatVar ([
406+ 'name ' => 'test ' ,
407+ 'tags ' => ['a ' , 'b ' , 'c ' ],
408+ 'meta ' => ['key ' => 'value ' ],
409+ 'count ' => 42 ,
410+ ]);
411+
412+ // All plain — no VarCloner needed
413+ $ this ->assertSame ('test ' , $ data ['name ' ]);
414+ $ this ->assertSame (['a ' , 'b ' , 'c ' ], $ data ['tags ' ]);
415+ $ this ->assertSame (['key ' => 'value ' ], $ data ['meta ' ]);
416+ $ this ->assertSame (42 , $ data ['count ' ]);
417+ $ this ->assertArrayNotHasKey ('_vd ' , $ data );
418+ }
419+
420+ public function testLargeArrayWithObjectBails (): void
421+ {
422+ $ d = new JsonDataFormatter ();
423+ $ obj = new \stdClass ();
424+ $ obj ->x = 1 ;
425+
426+ // 100 plain items + 1 object at the end
427+ $ input = [];
428+ for ($ i = 0 ; $ i < 100 ; $ i ++) {
429+ $ input ["k $ i " ] = "v $ i " ;
430+ }
431+ $ input ['obj ' ] = $ obj ;
432+
433+ $ data = $ d ->formatVar ($ input );
434+ $ this ->assertIsArray ($ data );
435+ // Object should still have _vd (entire array went through VarCloner on bail)
436+ $ this ->assertArrayHasKey ('_vd ' , $ data ['obj ' ]);
437+ }
438+
439+ public function testMaxDepthCutsNestedArrays (): void
440+ {
441+ $ d = new JsonDataFormatter ();
442+ $ d ->resetClonerOptions (['max_depth ' => 2 ]);
443+
444+ $ data = $ d ->formatVar (['a ' => ['b ' => ['c ' => ['d ' => 'deep ' ]]]]);
445+
446+ // depth 0: outer, depth 1: ['b'=>...], depth 2: ['c'=>...] entered,
447+ // depth 2 >= maxDepth so ['d'=>'deep'] gets cut
448+ $ this ->assertIsArray ($ data );
449+ $ this ->assertSame (['_cut ' => 1 ], $ data ['a ' ]['b ' ]['c ' ]);
450+ }
451+
452+ public function testEmptyNestedArray (): void
453+ {
454+ $ d = new JsonDataFormatter ();
455+
456+ $ data = $ d ->formatVar (['a ' => [], 'b ' => [1 , []]]);
457+ $ this ->assertSame ([], $ data ['a ' ]);
458+ $ this ->assertSame ([1 , []], $ data ['b ' ]);
459+ }
460+
461+ public function testMixedTypesInArray (): void
462+ {
463+ $ d = new JsonDataFormatter ();
464+
465+ $ data = $ d ->formatVar ([null , true , false , 0 , 1.5 , 'str ' , [1 ]]);
466+ $ this ->assertSame ([null , true , false , 0 , 1.5 , 'str ' , [1 ]], $ data );
467+ }
468+
469+ public function testStringTruncationInArray (): void
470+ {
471+ $ d = new JsonDataFormatter ();
472+ $ d ->resetClonerOptions (['max_string ' => 5 ]);
349473
474+ $ data = $ d ->formatVar (['short ' , 'ABCDEFGHIJ ' ]);
475+ $ this ->assertSame ('short ' , $ data [0 ]);
476+ $ this ->assertSame ('ABCDE[..5] ' , $ data [1 ]);
350477 }
351478}
0 commit comments