Passed
Pull Request — 2.11.x (#3971)
by Grégoire
03:18
created

Dumper::dump()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 13
c 2
b 0
f 0
dl 0
loc 21
ccs 12
cts 12
cp 1
rs 9.8333
cc 2
nc 2
nop 2
crap 2
1
<?php
2
3
namespace Doctrine\DBAL\Tools;
4
5
use ArrayIterator;
6
use ArrayObject;
7
use DateTimeInterface;
8
use Doctrine\Common\Collections\Collection;
0 ignored issues
show
Bug introduced by
The type Doctrine\Common\Collections\Collection was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use Doctrine\Common\Persistence\Proxy;
0 ignored issues
show
Bug introduced by
The type Doctrine\Common\Persistence\Proxy was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use stdClass;
11
use function array_keys;
12
use function assert;
13
use function class_exists;
14
use function count;
15
use function end;
16
use function explode;
17
use function extension_loaded;
18
use function get_class;
19
use function html_entity_decode;
20
use function ini_set;
21
use function is_array;
22
use function is_object;
23
use function is_string;
24
use function ob_get_clean;
25
use function ob_start;
26
use function strip_tags;
27
use function strlen;
28
use function strrpos;
29
use function substr;
30
use function var_dump;
31
32
/**
33
 * Static class used to dump the variable to be used on output.
34
 * Simplified port of Util\Debug from doctrine/common.
35
 *
36
 * @internal
37
 */
38
final class Dumper
39
{
40
    /**
41
     * Private constructor (prevents instantiation).
42
     */
43
    private function __construct()
44
    {
45
    }
46
47
    /**
48
     * Returns a dump of the public, protected and private properties of $var.
49
     *
50
     * @link https://xdebug.org/
51
     *
52
     * @param mixed $var      The variable to dump.
53
     * @param int   $maxDepth The maximum nesting level for object properties.
54
     */
55 233
    public static function dump($var, int $maxDepth = 2) : string
56
    {
57 233
        $html = ini_set('html_errors', '1');
58 233
        assert(is_string($html));
59
60 233
        if (extension_loaded('xdebug')) {
61 3
            ini_set('xdebug.var_display_max_depth', (string) $maxDepth);
62
        }
63
64 233
        $var = self::export($var, $maxDepth);
65
66 233
        ob_start();
67 233
        var_dump($var);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($var) looks like debug code. Are you sure you do not want to remove it?
Loading history...
68
69
        try {
70 233
            $output = ob_get_clean();
71 233
            assert(is_string($output));
72
73 233
            return strip_tags(html_entity_decode($output));
74
        } finally {
75 233
            ini_set('html_errors', $html);
76
        }
77
    }
78
79
    /**
80
     * @param mixed $var
81
     *
82
     * @return mixed
83
     */
84 242
    public static function export($var, int $maxDepth)
85
    {
86 242
        $return = null;
87 242
        $isObj  = is_object($var);
88
89 242
        if ($var instanceof Collection) {
90
            $var = $var->toArray();
91
        }
92
93 242
        if ($maxDepth === 0) {
94 117
            return is_object($var) ? get_class($var)
95 117
                : (is_array($var) ? 'Array(' . count($var) . ')' : $var);
96
        }
97
98 242
        if (is_array($var)) {
99 234
            $return = [];
100
101 234
            foreach ($var as $k => $v) {
102 234
                $return[$k] = self::export($v, $maxDepth - 1);
103
            }
104
105 234
            return $return;
106
        }
107
108 242
        if (! $isObj) {
109 239
            return $var;
110
        }
111
112 169
        $return = new stdClass();
113 169
        if ($var instanceof DateTimeInterface) {
114 95
            $return->__CLASS__ = get_class($var);
115 95
            $return->date      = $var->format('c');
116 95
            $return->timezone  = $var->getTimezone()->getName();
117
118 95
            return $return;
119
        }
120
121 166
        $return->__CLASS__ = self::getClass($var);
122
123 166
        if ($var instanceof Proxy) {
124
            $return->__IS_PROXY__          = true;
125
            $return->__PROXY_INITIALIZED__ = $var->__isInitialized();
126
        }
127
128 166
        if ($var instanceof ArrayObject || $var instanceof ArrayIterator) {
129 70
            $return->__STORAGE__ = self::export($var->getArrayCopy(), $maxDepth - 1);
130
        }
131
132 166
        return self::fillReturnWithClassAttributes($var, $return, $maxDepth);
133
    }
134
135
    /**
136
     * Fill the $return variable with class attributes
137
     * Based on obj2array function from {@see https://secure.php.net/manual/en/function.get-object-vars.php#47075}
138
     *
139
     * @param object $var
140
     *
141
     * @return mixed
142
     */
143 166
    private static function fillReturnWithClassAttributes($var, stdClass $return, int $maxDepth)
144
    {
145 166
        $clone = (array) $var;
146
147 166
        foreach (array_keys($clone) as $key) {
148 166
            $aux  = explode("\0", $key);
149 166
            $name = end($aux);
150 166
            if ($aux[0] === '') {
151 48
                $name .= ':' . ($aux[1] === '*' ? 'protected' : $aux[1] . ':private');
152
            }
153 166
            $return->$name = self::export($clone[$key], $maxDepth - 1);
154
        }
155
156 166
        return $return;
157
    }
158
159
    /**
160
     * @param object $object
161
     */
162 166
    private static function getClass($object) : string
163
    {
164 166
        $class = get_class($object);
165
166 166
        if (! class_exists(Proxy::class)) {
167 166
            return $class;
168
        }
169
170
        $pos = strrpos($class, '\\' . Proxy::MARKER . '\\');
171
172
        if ($pos === false) {
173
            return $class;
174
        }
175
176
        return substr($class, $pos + strlen(Proxy::MARKER) + 2);
177
    }
178
}
179