1111
1212namespace Symfony \Component \VarDumper \Cloner ;
1313
14+ use Symfony \Component \VarDumper \Dumper \DumperInternalsInterface ;
15+ use Symfony \Component \VarDumper \Dumper \Cursor ;
16+
1417/**
1518 * @author Nicolas Grekas <[email protected] > 1619 */
@@ -30,4 +33,169 @@ public function getRawData()
3033 {
3134 return $ this ->data ;
3235 }
36+
37+ /**
38+ * Dumps data with a DumperInternalsInterface dumper.
39+ */
40+ public function dump (DumperInternalsInterface $ dumper )
41+ {
42+ $ refs = array (0 );
43+ $ this ->dumpItem ($ dumper , new Cursor , $ refs , $ this ->data [0 ][0 ]);
44+ }
45+
46+ /**
47+ * Breadth-first dumping of items.
48+ *
49+ * @param DumperInternalsInterface $dumper The dumper being used for dumping.
50+ * @param Cursor $cursor A cursor used for tracking dumper state position.
51+ * @param array &$refs A map of all references discovered while dumping.
52+ * @param mixed $item A stub stdClass or the original value being dumped.
53+ */
54+ private function dumpItem ($ dumper , $ cursor , &$ refs , $ item )
55+ {
56+ $ cursor ->refIndex = $ cursor ->refTo = $ cursor ->refIsHard = false ;
57+
58+ if ($ item instanceof \stdClass) {
59+ if (property_exists ($ item , 'val ' )) {
60+ if (isset ($ item ->ref )) {
61+ if (isset ($ refs [$ r = $ item ->ref ])) {
62+ $ cursor ->refTo = $ refs [$ r ];
63+ $ cursor ->refIsHard = true ;
64+ } else {
65+ $ cursor ->refIndex = $ refs [$ r ] = ++$ refs [0 ];
66+ }
67+ }
68+ $ item = $ item ->val ;
69+ }
70+ if (isset ($ item ->ref )) {
71+ if (isset ($ refs [$ r = $ item ->ref ])) {
72+ if (false === $ cursor ->refTo ) {
73+ $ cursor ->refTo = $ refs [$ r ];
74+ $ cursor ->refIsHard = isset ($ item ->count );
75+ }
76+ } elseif (false !== $ cursor ->refIndex ) {
77+ $ refs [$ r ] = $ cursor ->refIndex ;
78+ } else {
79+ $ cursor ->refIndex = $ refs [$ r ] = ++$ refs [0 ];
80+ }
81+ }
82+ $ cut = isset ($ item ->cut ) ? $ item ->cut : 0 ;
83+
84+ if (isset ($ item ->pos ) && false === $ cursor ->refTo ) {
85+ $ children = $ this ->data [$ item ->pos ];
86+
87+ if ($ cursor ->stop ) {
88+ if ($ cut >= 0 ) {
89+ $ cut += count ($ children );
90+ }
91+ $ children = array ();
92+ }
93+ } else {
94+ $ children = array ();
95+ }
96+ switch (true ) {
97+ case isset ($ item ->bin ):
98+ $ dumper ->dumpString ($ cursor , $ item ->bin , true , $ cut );
99+
100+ return ;
101+
102+ case isset ($ item ->str ):
103+ $ dumper ->dumpString ($ cursor , $ item ->str , false , $ cut );
104+
105+ return ;
106+
107+ case isset ($ item ->count ):
108+ $ dumper ->enterArray ($ cursor , $ item ->count , !empty ($ item ->indexed ), (bool ) $ children );
109+ $ cut = $ this ->dumpChildren ($ dumper , $ cursor , $ refs , $ children , $ cut , empty ($ item ->indexed ) ? $ cursor ::HASH_ASSOC : $ cursor ::HASH_INDEXED );
110+ $ dumper ->leaveArray ($ cursor , $ item ->count , !empty ($ item ->indexed ), (bool ) $ children , $ cut );
111+
112+ return ;
113+
114+ case isset ($ item ->class ):
115+ $ dumper ->enterObject ($ cursor , $ item ->class , (bool ) $ children );
116+ $ cut = $ this ->dumpChildren ($ dumper , $ cursor , $ refs , $ children , $ cut , $ cursor ::HASH_OBJECT );
117+ $ dumper ->leaveObject ($ cursor , $ item ->class , (bool ) $ children , $ cut );
118+
119+ return ;
120+
121+ case isset ($ item ->res ):
122+ $ dumper ->enterResource ($ cursor , $ item ->res , (bool ) $ children );
123+ $ cut = $ this ->dumpChildren ($ dumper , $ cursor , $ refs , $ children , $ cut , $ cursor ::HASH_RESOURCE );
124+ $ dumper ->leaveResource ($ cursor , $ item ->res , (bool ) $ children , $ cut );
125+
126+ return ;
127+ }
128+ }
129+
130+ if ('array ' === $ type = gettype ($ item )) {
131+ $ dumper ->enterArray ($ cursor , 0 , true , 0 , 0 );
132+ $ dumper ->leaveArray ($ cursor , 0 , true , 0 , 0 );
133+ } else {
134+ $ dumper ->dumpScalar ($ cursor , $ type , $ item );
135+ }
136+ }
137+
138+ /**
139+ * Dumps children of hash structures.
140+ *
141+ * @param DumperInternalsInterface $dumper
142+ * @param Cursor $parentCursor The cursor of the parent hash.
143+ * @param array &$refs A map of all references discovered while dumping.
144+ * @param array $children The children to dump.
145+ * @param int $hashCut The number of items removed from the original hash.
146+ * @param int $hashType A Cursor::HASH_* const.
147+ *
148+ * @return int The final number of removed items.
149+ */
150+ private function dumpChildren ($ dumper , $ parentCursor , &$ refs , $ children , $ hashCut , $ hashType )
151+ {
152+ if ($ children ) {
153+ $ cursor = clone $ parentCursor ;
154+ ++$ cursor ->depth ;
155+ $ cursor ->hashType = $ hashType ;
156+ $ cursor ->hashIndex = 0 ;
157+ $ cursor ->hashLength = count ($ children );
158+ $ cursor ->hashCut = $ hashCut ;
159+ foreach ($ children as $ cursor ->hashKey => $ child ) {
160+ $ this ->dumpItem ($ dumper , $ cursor , $ refs , $ child );
161+ ++$ cursor ->hashIndex ;
162+ if ($ cursor ->stop ) {
163+ $ parentCursor ->stop = true ;
164+
165+ return $ hashCut >= 0 ? $ hashCut + $ children - $ cursor ->hashIndex : $ hashCut ;
166+ }
167+ }
168+ }
169+
170+ return $ hashCut ;
171+ }
172+
173+ /**
174+ * Portable variant of utf8_encode()
175+ *
176+ * @param string $s
177+ *
178+ * @return string
179+ *
180+ * @internal
181+ */
182+ public static function utf8Encode ($ s )
183+ {
184+ if (function_exists ('iconv ' )) {
185+ return iconv ('CP1252 ' , 'UTF-8 ' , $ s );
186+ } else {
187+ $ s .= $ s ;
188+ $ len = strlen ($ s );
189+
190+ for ($ i = $ len >> 1 , $ j = 0 ; $ i < $ len ; ++$ i , ++$ j ) {
191+ switch (true ) {
192+ case $ s [$ i ] < "\x80" : $ s [$ j ] = $ s [$ i ]; break ;
193+ case $ s [$ i ] < "\xC0" : $ s [$ j ] = "\xC2" ; $ s [++$ j ] = $ s [$ i ]; break ;
194+ default : $ s [$ j ] = "\xC3" ; $ s [++$ j ] = chr (ord ($ s [$ i ]) - 64 ); break ;
195+ }
196+ }
197+
198+ return substr ($ s , 0 , $ j );
199+ }
200+ }
33201}
0 commit comments