Passed
Branch master (ef264b)
by Pierrick
01:53
created

Dumper::eol()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 1
nc 2
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of NACL.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @copyright 2019 Nuglif (2018) Inc.
9
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
10
 * @author    Pierrick Charron <[email protected]>
11
 * @author    Charle Demers <[email protected]>
12
 */
13
14
declare(strict_types=1);
15
16
namespace Nuglif\Nacl;
17
18
class Dumper
19
{
20
    const PRETTY_PRINT               = 1 << 1;
21
    const SEPARATOR_AFTER_NON_SCALAR = 1 << 2;
22
    const SHORT_SINGLE_ELEMENT       = 1 << 3;
23
    const NO_TRAILING_SEPARATOR      = 1 << 4;
24
    const ROOT_BRACES                = 1 << 5;
25
    const QUOTE_STR                  = 1 << 6;
26
27
    /**
28
     * @var string
29
     */
30
    private $indentStr = '  ';
31
32
    /**
33
     * @var string
34
     */
35
    private $assign = ' ';
36
37
    /**
38
     * @var string
39
     */
40
    private $separator = ';';
41
42
    /**
43
     * @var string
44
     */
45
    private $listSeparator = ',';
46
47
    /**
48
     * @var int
49
     */
50
    private $depth = 0;
51
52
    /**
53
     * @var int
54
     */
55
    private $options;
56
57 528
    public function __construct($options = 0)
58
    {
59 528
        $this->options = $options;
60 528
    }
61
62
    public function setIndent($str)
63
    {
64
        $this->indentStr = $str;
65
    }
66
67
    public function setAssign($str)
68
    {
69
        $this->assign = $str;
70
    }
71
72
    public function setSeparator($str)
73
    {
74
        $this->separator = $str;
75
    }
76
77
    public function setListSeparator($str)
78
    {
79
        $this->listSeparator = $str;
80
    }
81
82 528
    public function dump($var)
83
    {
84 528
        return $this->dumpVar($var, !$this->hasOption(self::ROOT_BRACES));
85
    }
86
87 528
    private function dumpVar($var, $root = false)
88
    {
89 528
        $varType = gettype($var);
90 528
        switch ($varType) {
91 528
            case 'array':
92 528
                return $this->dumpArray($var, $root);
93 528
            case 'string':
94 528
                return $this->dumpString($var);
95 198
            case 'integer':
96 132
            case 'double':
97 132
            case 'boolean':
98 132
                return var_export($var, true);
99 66
            case 'NULL':
100 66
                return 'null';
101
        }
102
    }
103
104 528
    private function dumpArray(array $var, $root = false)
105
    {
106 528
        if ($this->isAssociativeArray($var)) {
107 462
            return $this->dumpAssociativeArray($var, $root);
108
        }
109
110 330
        return $this->dumpIndexedArray($var);
111
    }
112
113 462
    private function dumpAssociativeArray(array $var, $root = false)
114
    {
115 462
        $inline = $this->hasOption(self::SHORT_SINGLE_ELEMENT) && (1 === count($var));
116 462
        $str    = '';
117
118 462
        if (!$root && !$inline) {
119 362
            $str .= '{' . $this->eol();
120 362
            ++$this->depth;
121
        }
122
123 462
        $remainingElements = count($var);
124
125 462
        foreach ($var as $key => $value) {
126 462
            --$remainingElements;
127
128 462
            $requireSep = !($this->hasOption(self::NO_TRAILING_SEPARATOR) && !$inline && !$remainingElements) && (
129 430
                !is_array($value) ||
130
                (
131 298
                    $this->hasOption(self::SEPARATOR_AFTER_NON_SCALAR) &&
132 462
                    (!$this->hasOption(self::SHORT_SINGLE_ELEMENT) || 1 !== count($value) || is_int(key($value)))
133
                )
134
            );
135
136 462
            $str .= ($inline ? '' : $this->indent())
137 462
                . $this->dumpString($key)
138 462
                . $this->assign
139 462
                . $this->dumpVar($value)
140 462
                . ($requireSep ? $this->separator : '')
141 462
                . ($inline ? '' : $this->eol());
142
        }
143
144 462
        if (!$root && !$inline) {
145 362
            --$this->depth;
146 362
            $str .= $this->indent() . '}';
147
        }
148
149 462
        return $str;
150
    }
151
152 330
    private function dumpIndexedArray(array $var)
153
    {
154 330
        $count = count($var);
155 330
        if (0 === $count) {
156
            return '[]';
157
        }
158
159 330
        $str = '[' . $this->eol();
160 330
        ++$this->depth;
161 330
        for ($i = 0; $i < $count; ++$i) {
162 330
            $str .= $this->indent() . rtrim($this->dumpVar($var[$i]), $this->separator);
0 ignored issues
show
Bug introduced by
It seems like $this->dumpVar($var[$i]) can also be of type null; however, parameter $string of rtrim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

162
            $str .= $this->indent() . rtrim(/** @scrutinizer ignore-type */ $this->dumpVar($var[$i]), $this->separator);
Loading history...
163 330
            if ($count - 1 !== $i) {
164 330
                $str .= $this->listSeparator;
165
            }
166 330
            $str .= $this->eol();
167
        }
168 330
        --$this->depth;
169 330
        $str .= $this->indent() . ']';
170
171 330
        return $str;
172
    }
173
174 528
    private function dumpString($var)
175
    {
176 528
        if (!$this->hasOption(self::QUOTE_STR) && preg_match('#^(' . Lexer::REGEX_NAME . ')$#A', $var)) {
177 448
            switch ($var) {
178 448
                case 'true':
179 448
                case 'false':
180 448
                case 'on':
181 448
                case 'off':
182 448
                case 'yes':
183 448
                case 'no':
184 448
                case 'null':
185 64
                    return '"' . $var . '"';
186
                default:
187 448
                    return $var;
188
            }
189
        }
190
191 528
        return '"' . strtr($var, [
192 528
            "\b" => '\\b',
193
            "\f" => '\\f',
194
            "\r" => '\\r',
195
            "\n" => '\\n',
196
            "\t" => '\\t',
197
            '"'  => '\\"',
198
            '\\' => '\\\\',
199 528
        ]) . '"';
200
    }
201
202 528
    private function isAssociativeArray(array $var)
203
    {
204 528
        $i = 0;
205 528
        foreach (array_keys($var) as $key) {
206 528
            if ($key !== $i++) {
207 462
                return true;
208
            }
209
        }
210
211 330
        return false;
212
    }
213
214 464
    private function eol()
215
    {
216 464
        return $this->hasOption(self::PRETTY_PRINT) ? PHP_EOL : '';
217
    }
218
219 464
    private function indent()
220
    {
221 464
        return $this->hasOption(self::PRETTY_PRINT) ? str_repeat($this->indentStr, $this->depth) : '';
222
    }
223
224 528
    private function hasOption($opt)
225
    {
226 528
        return $opt & $this->options;
227
    }
228
}
229