Toon::parseLines()   B
last analyzed

Complexity

Conditions 9
Paths 3

Size

Total Lines 60
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 35
nc 3
nop 3
dl 0
loc 60
rs 8.0555
c 0
b 0
f 0

How to fix   Long Method   

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 Squareetlabs\LaravelToon\Toon;
6
7
class Toon
8
{
9
    public static function encode(mixed $data, ?EncodeOptions $options = null): string
10
    {
11
        $options ??= new EncodeOptions();
12
13
        return Encoders::encode($data, $options);
14
    }
15
16
    public static function encodeCompact(mixed $data): string
17
    {
18
        return self::encode($data, EncodeOptions::compact());
19
    }
20
21
    public static function encodeReadable(mixed $data): string
22
    {
23
        return self::encode($data, EncodeOptions::readable());
24
    }
25
26
    public static function encodeTabular(mixed $data): string
27
    {
28
        return self::encode($data, EncodeOptions::tabular());
29
    }
30
31
    public static function decode(string $toon): mixed
32
    {
33
        $lines = explode("\n", trim($toon));
34
35
        return self::parseLines($lines);
36
    }
37
38
    private static function parseLines(array $lines, int &$index = 0, int $expectedIndent = 0): mixed
39
    {
40
        $result = [];
41
        $isObject = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $isObject is dead and can be removed.
Loading history...
42
        $isList = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $isList is dead and can be removed.
Loading history...
43
44
        while ($index < count($lines)) {
45
            $line = $lines[$index];
46
            $indent = self::getIndent($line);
47
            $content = trim($line);
48
49
            if ('' === $content) {
50
                ++$index;
51
52
                continue;
53
            }
54
55
            if ($indent < $expectedIndent) {
56
                break;
57
            }
58
59
            if ($indent > $expectedIndent) {
60
                ++$index;
61
62
                continue;
63
            }
64
65
            if (str_contains($content, Constants::OBJECT_MARKER)) {
66
                $isObject = true;
67
                [$key, $value] = self::parseObjectLine($content);
68
                ++$index;
69
70
                if ($index < count($lines)) {
71
                    $nextLine = $lines[$index];
72
                    $nextIndent = self::getIndent($nextLine);
73
                    if ($nextIndent > $expectedIndent) {
74
                        $result[$key] = self::parseLines($lines, $index, $nextIndent);
75
76
                        continue;
77
                    }
78
                }
79
80
                $result[$key] = $value;
81
82
                continue;
83
            }
84
85
            if (str_contains($content, Constants::ARRAY_MARKER)) {
86
                $isList = true;
87
                $result[] = self::parseArrayLine($content);
88
                ++$index;
89
90
                continue;
91
            }
92
93
            $result[] = Primitives::decode($content);
94
            ++$index;
95
        }
96
97
        return $result;
98
    }
99
100
    private static function parseObjectLine(string $line): array
101
    {
102
        $parts = explode(Constants::OBJECT_MARKER, $line, 2);
103
        $key = trim($parts[0]);
104
        $value = isset($parts[1]) ? trim($parts[1]) : null;
105
106
        if ('' === $value || null === $value) {
107
            return [$key, null];
108
        }
109
110
        return [$key, Primitives::decode($value)];
111
    }
112
113
    private static function parseArrayLine(string $line): mixed
114
    {
115
        // Extract array length
116
        if (preg_match('/^(\d+)\]/', $line, $matches)) {
117
            $length = (int)$matches[1];
118
            $line = substr($line, strlen($matches[0]));
119
            $line = trim($line);
120
121
            // Check for field headers (tabular format)
122
            if (str_contains($line, Constants::ARRAY_FIELD_WRAPPER_START)) {
123
                preg_match('/\{([^}]+)\}/', $line, $fieldMatches);
124
                if (isset($fieldMatches[1])) {
125
                    $fields = explode(Constants::FIELD_DELIMITER, $fieldMatches[1]);
126
127
                    return [
128
                        'length' => $length,
129
                        'fields' => $fields,
130
                        'type' => 'tabular',
131
                    ];
132
                }
133
            }
134
135
            // Extract values
136
            if (str_contains($line, Constants::ARRAY_HEADER_DELIMITER)) {
137
                $parts = explode(Constants::ARRAY_HEADER_DELIMITER, $line, 2);
138
                $values = explode(Constants::FIELD_DELIMITER, trim($parts[1] ?? ''));
139
140
                return array_map(fn ($v) => Primitives::decode($v), $values);
141
            }
142
        }
143
144
        return [];
145
    }
146
147
    private static function getIndent(string $line): int
148
    {
149
        $count = 0;
150
        foreach (str_split($line) as $char) {
151
            if (' ' === $char) {
152
                ++$count;
153
            } else {
154
                break;
155
            }
156
        }
157
158
        return (int)($count / 2);
159
    }
160
}
161
162