Passed
Push — master ( 244aa0...c1114e )
by Wilmer
27:09 queued 12:07
created

ArrayParser::parseString()   B

Complexity

Conditions 10
Paths 64

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 14
nc 64
nop 2
dl 0
loc 24
rs 7.6666
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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