Test Failed
Push — main ( c8394f...8477f1 )
by Rafael
66:21
created

Data::dumpItem()   F

Complexity

Conditions 26
Paths 2355

Size

Total Lines 83
Code Lines 65

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 26
eloc 65
nc 2355
nop 4
dl 0
loc 83
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Symfony\Component\VarDumper\Cloner;
13
14
use Symfony\Component\VarDumper\Caster\Caster;
15
16
/**
17
 * @author Nicolas Grekas <[email protected]>
18
 */
19
class Data
20
{
21
    private $data;
22
    private $position = 0;
23
    private $key = 0;
24
    private $maxDepth = 20;
25
    private $maxItemsPerDepth = -1;
26
    private $useRefHandles = -1;
27
28
    /**
29
     * @param array $data A array as returned by ClonerInterface::cloneVar()
30
     */
31
    public function __construct(array $data)
32
    {
33
        $this->data = $data;
34
    }
35
36
    /**
37
     * @return array The raw data structure
38
     */
39
    public function getRawData()
40
    {
41
        return $this->data;
42
    }
43
44
    /**
45
     * Returns a depth limited clone of $this.
46
     *
47
     * @param int $maxDepth The max dumped depth level
48
     *
49
     * @return self A clone of $this
50
     */
51
    public function withMaxDepth($maxDepth)
52
    {
53
        $data = clone $this;
54
        $data->maxDepth = (int) $maxDepth;
55
56
        return $data;
57
    }
58
59
    /**
60
     * Limits the number of elements per depth level.
61
     *
62
     * @param int $maxItemsPerDepth The max number of items dumped per depth level
63
     *
64
     * @return self A clone of $this
65
     */
66
    public function withMaxItemsPerDepth($maxItemsPerDepth)
67
    {
68
        $data = clone $this;
69
        $data->maxItemsPerDepth = (int) $maxItemsPerDepth;
70
71
        return $data;
72
    }
73
74
    /**
75
     * Enables/disables objects' identifiers tracking.
76
     *
77
     * @param bool $useRefHandles False to hide global ref. handles
78
     *
79
     * @return self A clone of $this
80
     */
81
    public function withRefHandles($useRefHandles)
82
    {
83
        $data = clone $this;
84
        $data->useRefHandles = $useRefHandles ? -1 : 0;
85
86
        return $data;
87
    }
88
89
    /**
90
     * Seeks to a specific key in nested data structures.
91
     *
92
     * @param string|int $key The key to seek to
93
     *
94
     * @return self|null A clone of $this of null if the key is not set
95
     */
96
    public function seek($key)
97
    {
98
        $item = $this->data[$this->position][$this->key];
99
100
        if (!$item instanceof Stub || !$item->position) {
101
            return;
102
        }
103
        $keys = array($key);
104
105
        switch ($item->type) {
106
            case Stub::TYPE_OBJECT:
107
                $keys[] = Caster::PREFIX_DYNAMIC . $key;
108
                $keys[] = Caster::PREFIX_PROTECTED . $key;
109
                $keys[] = Caster::PREFIX_VIRTUAL . $key;
110
                $keys[] = "\0$item->class\0$key";
111
            case Stub::TYPE_ARRAY:
112
            case Stub::TYPE_RESOURCE:
113
                break;
114
            default:
115
                return;
116
        }
117
118
        $data = null;
119
        $children = $this->data[$item->position];
120
121
        foreach ($keys as $key) {
122
            if (isset($children[$key]) || array_key_exists($key, $children)) {
123
                $data = clone $this;
124
                $data->key = $key;
125
                $data->position = $item->position;
126
                break;
127
            }
128
        }
129
130
        return $data;
131
    }
132
133
    /**
134
     * Dumps data with a DumperInterface dumper.
135
     */
136
    public function dump(DumperInterface $dumper)
137
    {
138
        $refs = array(0);
139
        $this->dumpItem($dumper, new Cursor(), $refs, $this->data[$this->position][$this->key]);
140
    }
141
142
    /**
143
     * Depth-first dumping of items.
144
     *
145
     * @param DumperInterface $dumper The dumper being used for dumping
146
     * @param Cursor          $cursor A cursor used for tracking dumper state position
147
     * @param array           &$refs  A map of all references discovered while dumping
148
     * @param mixed           $item   A Stub object or the original value being dumped
149
     */
150
    private function dumpItem($dumper, $cursor, &$refs, $item)
151
    {
152
        $cursor->refIndex = 0;
153
        $cursor->softRefTo = $cursor->softRefHandle = $cursor->softRefCount = 0;
154
        $cursor->hardRefTo = $cursor->hardRefHandle = $cursor->hardRefCount = 0;
155
        $firstSeen = true;
156
157
        if (!$item instanceof Stub) {
158
            $cursor->attr = array();
159
            $type = gettype($item);
160
        } elseif (Stub::TYPE_REF === $item->type) {
161
            if ($item->handle) {
162
                if (!isset($refs[$r = $item->handle - (PHP_INT_MAX >> 1)])) {
163
                    $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0];
164
                } else {
165
                    $firstSeen = false;
166
                }
167
                $cursor->hardRefTo = $refs[$r];
168
                $cursor->hardRefHandle = $this->useRefHandles & $item->handle;
169
                $cursor->hardRefCount = $item->refCount;
170
            }
171
            $cursor->attr = $item->attr;
172
            $type = $item->class ?: gettype($item->value);
173
            $item = $item->value;
174
        }
175
        if ($item instanceof Stub) {
176
            if ($item->refCount) {
177
                if (!isset($refs[$r = $item->handle])) {
178
                    $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0];
179
                } else {
180
                    $firstSeen = false;
181
                }
182
                $cursor->softRefTo = $refs[$r];
183
            }
184
            $cursor->softRefHandle = $this->useRefHandles & $item->handle;
185
            $cursor->softRefCount = $item->refCount;
186
            $cursor->attr = $item->attr;
187
            $cut = $item->cut;
188
189
            if ($item->position && $firstSeen) {
190
                $children = $this->data[$item->position];
191
192
                if ($cursor->stop) {
193
                    if ($cut >= 0) {
194
                        $cut += count($children);
195
                    }
196
                    $children = array();
197
                }
198
            } else {
199
                $children = array();
200
            }
201
            switch ($item->type) {
202
                case Stub::TYPE_STRING:
203
                    $dumper->dumpString($cursor, $item->value, Stub::STRING_BINARY === $item->class, $cut);
204
                    break;
205
206
                case Stub::TYPE_ARRAY:
207
                    $item = clone $item;
208
                    $item->type = $item->class;
209
                    $item->class = $item->value;
210
                    // No break;
211
                case Stub::TYPE_OBJECT:
212
                case Stub::TYPE_RESOURCE:
213
                    $withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth;
214
                    $dumper->enterHash($cursor, $item->type, $item->class, $withChildren);
215
                    if ($withChildren) {
216
                        $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class);
217
                    } elseif ($children && 0 <= $cut) {
218
                        $cut += count($children);
219
                    }
220
                    $dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut);
221
                    break;
222
223
                default:
224
                    throw new \RuntimeException(sprintf('Unexpected Stub type: %s', $item->type));
225
            }
226
        } elseif ('array' === $type) {
227
            $dumper->enterHash($cursor, Cursor::HASH_INDEXED, 0, false);
228
            $dumper->leaveHash($cursor, Cursor::HASH_INDEXED, 0, false, 0);
229
        } elseif ('string' === $type) {
230
            $dumper->dumpString($cursor, $item, false, 0);
231
        } else {
232
            $dumper->dumpScalar($cursor, $type, $item);
233
        }
234
    }
235
236
    /**
237
     * Dumps children of hash structures.
238
     *
239
     * @param DumperInterface $dumper
240
     * @param Cursor          $parentCursor The cursor of the parent hash
241
     * @param array           &$refs        A map of all references discovered while dumping
242
     * @param array           $children     The children to dump
243
     * @param int             $hashCut      The number of items removed from the original hash
244
     * @param string          $hashType     A Cursor::HASH_* const
245
     * @param bool            $dumpKeys     Whether keys should be dumped or not
246
     *
247
     * @return int The final number of removed items
248
     */
249
    private function dumpChildren($dumper, $parentCursor, &$refs, $children, $hashCut, $hashType, $dumpKeys)
250
    {
251
        $cursor = clone $parentCursor;
252
        ++$cursor->depth;
253
        $cursor->hashType = $hashType;
254
        $cursor->hashIndex = 0;
255
        $cursor->hashLength = count($children);
256
        $cursor->hashCut = $hashCut;
257
        foreach ($children as $key => $child) {
258
            $cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key);
259
            $cursor->hashKey = $dumpKeys ? $key : null;
260
            $this->dumpItem($dumper, $cursor, $refs, $child);
261
            if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) {
262
                $parentCursor->stop = true;
263
264
                return $hashCut >= 0 ? $hashCut + $cursor->hashLength - $cursor->hashIndex : $hashCut;
265
            }
266
        }
267
268
        return $hashCut;
269
    }
270
}
271