Passed
Push — master ( b62344...459625 )
by Alexander
01:46
created

ArrayItemExporter::renderArray()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 11
ccs 8
cts 8
cp 1
rs 10
cc 4
nc 6
nop 1
crap 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Cycle\Schema\Converter\SchemaToPHP;
6
7
final class ArrayItemExporter
8
{
9
    private const MIX_LINE_LENGTH = 120;
10
11
    public ?string $key;
12
    /** @var mixed */
13
    public $value;
14
    public bool $wrapValue = true;
15
    public bool $wrapKey;
16
17
    /**
18
     * @param null|string $key
19
     * @param mixed $value
20
     * @param bool $wrapKey
21
     */
22 2
    public function __construct(?string $key, $value = null, bool $wrapKey = false)
23
    {
24 2
        $this->key = $key;
25 2
        $this->value = $value;
26 2
        $this->wrapKey = $wrapKey;
27 2
    }
28
29 2
    public function __toString()
30
    {
31 2
        $result = '';
32 2
        if ($this->key !== null) {
33 1
            $result = $this->wrapKey ? "'{$this->key}' => " : "{$this->key} => ";
34
        }
35 2
        return $result . $this->renderValue($this->value);
36
    }
37
38
    /**
39
     * @param mixed $value
40
     * @return string
41
     */
42 2
    private function renderValue($value): string
43
    {
44 2
        switch (true) {
45
            case $value === null:
46 2
                return 'null';
47 1
            case is_bool($value):
48 1
                return $value ? 'true' : 'false';
49 1
            case is_array($value):
50 1
                return $this->renderArray($value);
51 1
            case !$this->wrapValue || is_int($value) || $value instanceof self:
52 1
                return (string)$value;
53 1
            case is_string($value):
54 1
                return "'" . addslashes($value) . "'";
55
            default:
56
                return "unserialize('" . addslashes(serialize($value)) . "')";
57
        }
58
    }
59
60 1
    private function renderArray(array $value): string
61
    {
62 1
        $aiKeys = $this->isAutoIncrementedKeys($value);
63 1
        $inline = $aiKeys && $this->isScalarArrayValues($value);
64 1
        if ($inline) {
65 1
            $result = $this->renderArrayInline($value, !$aiKeys);
66 1
            if (strlen($result) <= self::MIX_LINE_LENGTH) {
67 1
                return $result;
68
            }
69
        }
70 1
        return $this->renderArrayBlock($value, !$aiKeys);
71
    }
72
73 1
    private function renderArrayInline(array $value, bool $withKeys = true): string
74
    {
75 1
        $elements = [];
76 1
        foreach ($value as $key => $item) {
77 1
            $str = '';
78 1
            if (!$item instanceof ArrayItemExporter && $withKeys) {
79
                $str .= is_int($key) ? "{$key} => " : "'{$key}' => ";
80
            }
81 1
            $elements[] = $str . $this->renderValue($item);
82
        }
83 1
        return '[' . implode(', ', $elements) . ']';
84
    }
85 1
    private function renderArrayBlock(array $value, bool $withKeys = true): string
86
    {
87 1
        $result = '[';
88 1
        foreach ($value as $key => $item) {
89 1
            $result .= "\n";
90 1
            if (!$item instanceof ArrayItemExporter && $withKeys) {
91 1
                $result .= is_int($key) ? "{$key} => " : "'{$key}' => ";
92
            }
93 1
            $result .= $this->renderValue($item) . ',';
94
        }
95 1
        return str_replace("\n", "\n    ", $result) . "\n]";
96
    }
97
98 1
    private function isAutoIncrementedKeys(array $array): bool
99
    {
100 1
        return count($array) === 0 || array_keys($array) === range(0, count($array) - 1);
101
    }
102 1
    private function isScalarArrayValues(array $array): bool
103
    {
104 1
        foreach ($array as $value) {
105 1
            if (!is_scalar($value)) {
106 1
                return false;
107
            }
108
        }
109 1
        return true;
110
    }
111
}
112