Passed
Push — master ( 80d34d...67ed39 )
by Paul
02:55
created

Dump::inspect()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 10
nc 4
nop 1
dl 0
loc 13
rs 9.9332
c 1
b 0
f 0
1
<?php
2
3
namespace GeminiLabs\BlackBar;
4
5
/**
6
 * @see: https://github.com/jacobstr/dumpling
7
 */
8
class Dump
9
{
10
    public $depth;
11
    public $ignore;
12
13
    protected $level = 0;
14
    protected $result = [];
15
    protected $stack = [];
16
17
    /**
18
     * @param mixed $value
19
     */
20
    public function dump($value, int $depth = 3, array $ignore = []): string
21
    {
22
        $this->depth = $depth;
23
        $this->ignore = $ignore;
24
        $this->reset();
25
        $this->inspect($value);
26
        $result = implode('', $this->result);
27
        $result = rtrim($result, "\n");
28
        $this->reset();
29
        return $result;
30
    }
31
32
    protected function formatKey(string $key): string
33
    {
34
        $result = [];
35
        $result[] = str_repeat(' ', $this->level * 4).'[';
36
        if (is_string($key) && "\0" === $key[0]) {
37
            $keyParts = explode("\0", $key);
38
            $result[] = $keyParts[2].(('*' === $keyParts[1]) ? ':protected' : ':private');
39
        } else {
40
            $result[] = $key;
41
        }
42
        $result[] = '] => ';
43
        return implode('', $result);
44
    }
45
46
    /**
47
     * @param mixed $subject
48
     */
49
    protected function inspect($subject): void
50
    {
51
        ++$this->level;
52
        if ($subject instanceof \Closure) {
53
            $this->inspectClosure($subject);
54
        } elseif (is_object($subject)) {
55
            $this->inspectObject($subject);
56
        } elseif (is_array($subject)) {
57
            $this->inspectArray($subject);
58
        } else {
59
            $this->inspectPrimitive($subject);
60
        }
61
        --$this->level;
62
    }
63
64
    protected function inspectArray(array $subject): void
65
    {
66
        if ($this->level > $this->depth) {
67
            $this->result[] = "Nested Array\n";
68
            return;
69
        }
70
        if (empty($subject)) {
71
            $this->result[] = "Array ()\n";
72
            return;
73
        }
74
        $this->result[] = "Array (\n";
75
        foreach ($subject as $key => $val) {
76
            if (false === $this->isIgnoredKey($key)) {
77
                $this->result[] = str_repeat(' ', $this->level * 4).'['.$key.'] => ';
78
                $this->inspect($val);
79
            }
80
        }
81
        $this->result[] = str_repeat(' ', ($this->level - 1) * 4).")\n";
82
    }
83
84
    protected function inspectClosure(\Closure $subject): void
85
    {
86
        $reflection = new \ReflectionFunction($subject);
87
        $params = array_map(function ($param) {
88
            return ($param->isPassedByReference() ? '&$' : '$').$param->name;
89
        }, $reflection->getParameters());
90
        $this->result[] = 'Closure ('.implode(', ', $params).') { ... }'."\n";
91
    }
92
93
    /**
94
     * @param object $subject
95
     */
96
    protected function inspectObject($subject): void
97
    {
98
        $classname = get_class($subject);
99
        if ($this->level > $this->depth) {
100
            $this->result[] = 'Nested '.$classname." Object\n";
101
            return;
102
        }
103
        if ($subject instanceof \ArrayObject) {
104
            $this->result[] = $classname." ArrayObject (\n";
105
        } else {
106
            $this->result[] = $classname." Object (\n";
107
            $subject = (array) $subject;
108
        }
109
        foreach ($subject as $key => $val) {
110
            if (false === $this->isIgnoredKey($key)) {
111
                $this->result[] = $this->formatKey($key);
112
                $this->inspect($val);
113
            }
114
        }
115
        $this->result[] = str_repeat(' ', ($this->level - 1) * 4).")\n";
116
    }
117
118
    /**
119
     * @param mixed $subject
120
     */
121
    protected function inspectPrimitive($subject): void
122
    {
123
        if (true === $subject) {
124
            $subject = '(bool) true';
125
        } elseif (false === $subject) {
126
            $subject = '(bool) false';
127
        } elseif (null === $subject) {
128
            $subject = '(null)';
129
        }
130
        $this->result[] = $subject."\n";
131
    }
132
133
    /**
134
     * @param string $key
135
     */
136
    protected function isIgnoredKey($key): bool
137
    {
138
        return in_array($key, $this->ignore);
139
    }
140
141
    protected function reset(): void
142
    {
143
        $this->level = 0;
144
        $this->result = [];
145
        $this->stack = [];
146
    }
147
}
148
149