Passed
Push — master ( 03d3d0...cea9c0 )
by Alexander
07:36 queued 05:58
created

ArrayParser   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 98
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 38
c 0
b 0
f 0
dl 0
loc 98
ccs 39
cts 39
cp 1
rs 10
wmc 20

3 Methods

Rating   Name   Duplication   Size   Complexity  
B parseString() 0 24 10
A parse() 0 11 3
B parseArray() 0 29 7
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Pgsql;
6
7
use function in_array;
8
use function strlen;
9
10
/**
11
 * The class converts PostgreSQL array representation to PHP array.
12
 */
13
final class ArrayParser
14
{
15
    /**
16
     * @var string Character used in array
17
     */
18
    private string $delimiter = ',';
19
20
    /**
21
     * Convert array from PostgreSQL to PHP
22
     *
23
     * @param string|null $value string to be converted
24
     *
25
     * @return array|null
26
     */
27 2
    public function parse(?string $value): ?array
28
    {
29 2
        if ($value === null) {
30 2
            return null;
31
        }
32
33 2
        if ($value === '{}') {
34 1
            return [];
35
        }
36
37 2
        return $this->parseArray($value);
38
    }
39
40
    /**
41
     * Pares PgSQL array encoded in string.
42
     *
43
     * @param string $value
44
     * @param int $i parse starting position.
45
     *
46
     * @return array
47
     */
48 2
    private function parseArray(string $value, int &$i = 0): array
49
    {
50 2
        $result = [];
51 2
        $len = strlen($value);
52
53 2
        for (++$i; $i < $len; ++$i) {
54 2
            switch ($value[$i]) {
55 2
                case '{':
56 2
                    $result[] = $this->parseArray($value, $i);
57 2
                    break;
58 2
                case '}':
59 2
                    break 2;
60 2
                case $this->delimiter:
61
                    /** `{}` case */
62 2
                    if (empty($result)) {
63 1
                        $result[] = null;
64
                    }
65
66
                    /** `{,}` case */
67 2
                    if (in_array($value[$i + 1], [$this->delimiter, '}'], true)) {
68 1
                        $result[] = null;
69
                    }
70 2
                    break;
71
                default:
72 2
                    $result[] = $this->parseString($value, $i);
73
            }
74
        }
75
76 2
        return $result;
77
    }
78
79
    /**
80
     * Parses PgSQL encoded string.
81
     *
82
     * @param string $value
83
     * @param int $i parse starting position.
84
     *
85
     * @return string|null
86
     */
87 2
    private function parseString(string $value, int &$i): ?string
88
    {
89 2
        $isQuoted = $value[$i] === '"';
90 2
        $stringEndChars = $isQuoted ? ['"'] : [$this->delimiter, '}'];
91 2
        $result = '';
92 2
        $len = strlen($value);
93
94 2
        for ($i += $isQuoted ? 1 : 0; $i < $len; ++$i) {
95 2
            if (in_array($value[$i], ['\\', '"'], true) && in_array($value[$i + 1], [$value[$i], '"'], true)) {
96 2
                ++$i;
97 2
            } elseif (in_array($value[$i], $stringEndChars, true)) {
98 2
                break;
99
            }
100
101 2
            $result .= $value[$i];
102
        }
103
104 2
        $i -= $isQuoted ? 0 : 1;
105
106 2
        if (!$isQuoted && $result === 'NULL') {
107 2
            $result = null;
108
        }
109
110 2
        return $result;
111
    }
112
}
113