Passed
Push — master ( 4b3d26...06dcf5 )
by Enjoys
12:36 queued 13s
created

Parser::parseValue()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 30
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5

Importance

Changes 2
Bugs 0 Features 2
Metric Value
cc 5
eloc 19
c 2
b 0
f 2
nc 5
nop 1
dl 0
loc 30
ccs 12
cts 12
cp 1
crap 5
rs 9.3222
1
<?php
2
3
declare(strict_types=1);
4
5
6
namespace Enjoys\Dotenv\Parser;
7
8
9
use Enjoys\Dotenv\Parser\Env\Comment;
10
use Enjoys\Dotenv\Parser\Env\Key;
11
use Enjoys\Dotenv\Parser\Env\Value;
12
use Enjoys\Dotenv\Parser\Lines\CommentLine;
13
use Enjoys\Dotenv\Parser\Lines\EmptyLine;
14
use Enjoys\Dotenv\Parser\Lines\EnvLine;
15
use Enjoys\Dotenv\Parser\Lines\LineInterface;
16
use Enjoys\Dotenv\Parser\Lines\Multiline;
17
18
final class Parser implements ParserInterface
19
{
20
21
    /**
22
     * @param string $content
23
     * @return array<string, string|null>
24
     */
25 42
    public function parseEnv(string $content): array
26
    {
27 42
        $envArray = [];
28
        /** @var LineInterface $line */
29 42
        foreach ($this->parseLines($content) as $line) {
30 41
            if ($line instanceof EnvLine){
31 41
                $envArray[$line->getKey()->getValue()] = $line->getValue()?->getValue();
32
            }
33
        }
34 40
        return $envArray;
35
    }
36
37
    /**
38
     * @param string $content
39
     * @return array<array-key, LineInterface>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, LineInterface> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, LineInterface>.
Loading history...
40
     */
41 1
    public function parseStructure(string $content): array
42
    {
43 1
        $structure = [];
44
        /** @var LineInterface $line */
45 1
        foreach ($this->parseLines($content) as $line) {
46 1
            if ($line instanceof EnvLine){
47 1
                $structure[$line->getKey()->getValue()] = $line;
48 1
                continue;
49
            }
50 1
            $structure[] = $line;
51
        }
52 1
        return $structure;
53
    }
54
55 53
    public function parseLines(string $content): \Generator
56
    {
57 53
        foreach (Multiline::handle(
58 53
            array_map(
59
                'trim',
60 53
                preg_split("/\R/", $content)
61
            )
62
        ) as $line) {
63 53
            if (empty($line)) {
64 39
                yield new EmptyLine();
65 39
                continue;
66
            }
67
68 52
            if (str_starts_with($line, '#')) {
69 7
                yield new CommentLine($line);
70 7
                continue;
71
            }
72
73 52
            [$key, $value, $comment] = $this->parseEnvLine($line);
74 51
            yield new EnvLine(
75
                $key,
76
                $value,
77
                $comment
78
            );
79
        }
80
    }
81
82
    /**
83
     * @param string $rawLine
84
     * @return array{0: Key, 1: Value|null, 2: Comment|null}
85
     */
86 52
    private function parseEnvLine(string $rawLine): array
87
    {
88
        /**
89
         * $explodedLine[0] - rawKey
90
         * $explodedLine[1] - rawValue
91
         * @var string[] $explodedLine
92
         */
93 52
        $explodedLine = array_map('trim', explode('=', $rawLine, 2));
94
95
        return [
96 52
            new Key($explodedLine[0]),
97 51
            ...$this->parseValue($explodedLine[1] ??= null)
98
        ];
99
    }
100
101
    /**
102
     * @param string|null $rawValue
103
     * @return array<int, Value|Comment|null>
104
     */
105 51
    private function parseValue(?string $rawValue): array
106
    {
107 51
        if ($rawValue === null) {
108
            return [
109 11
                null,
110
                null
111
            ];
112
        }
113
114 44
        preg_match(
115
            '/^(?<value>([\'"])(?:(?!\1|\\\\).|\\\\.)*?\2)(?<comment>.*)?/',
116
            $rawValue,
117
            $matches,
118
            PREG_UNMATCHED_AS_NULL
119
        );
120
121 44
        $matches['value'] ??= false;
122 44
        $matches['comment'] ??= null;
123
124 44
        if ($matches['value']) {
125
            return [
126 22
                new Value($matches['value']),
127 22
                $matches['comment'] ? new Comment($matches['comment']) : null
128
            ];
129
        }
130
131 40
        $unquotedValue = array_map('trim', explode('#', $rawValue, 2));
132
        return [
133 40
            new Value($unquotedValue[0]),
134 40
            ($unquotedValue[1] ?? null) ? new Comment($unquotedValue[1]) : null
135
        ];
136
    }
137
138
}
139