Passed
Push — master ( c316a0...31177f )
by Def
02:09
created

MessageSource::getMessages()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 4
nop 2
dl 0
loc 12
ccs 7
cts 7
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Translator\Message\Php;
6
7
use InvalidArgumentException;
8
use Yiisoft\Translator\MessageReaderInterface;
9
use Yiisoft\Translator\MessageWriterInterface;
10
use function array_key_exists;
11
use function is_string;
12
13
final class MessageSource implements MessageReaderInterface, MessageWriterInterface
14
{
15
    private string $path;
16
    private array $messages = [];
17
18 12
    public function __construct(string $path)
19
    {
20 12
        $this->path = $path;
21 12
    }
22
23 4
    public function getMessage(string $id, string $category, string $locale, array $parameters = []): ?string
24
    {
25 4
        if (!isset($this->messages[$category][$locale])) {
26 4
            $this->read($category, $locale);
27
        }
28
29 4
        return $this->messages[$category][$locale][$id] ?? null;
30
    }
31
32 2
    public function getMessages(string $category, string $locale): array
33
    {
34 2
        if (!isset($this->messages[$category][$locale])) {
35 2
            $this->read($category, $locale);
36
        }
37
38 2
        $messages = $this->messages[$category][$locale] ?? [];
39 2
        foreach ($messages as &$message) {
40 2
            $message = ['message' => $message];
41
        }
42
43 2
        return $messages;
44
    }
45
46 9
    private function getFilePath(string $category, string $locale, bool $withCreateDir = false): string
47
    {
48 9
        $filePath = $this->path . DIRECTORY_SEPARATOR . $locale;
49 9
        if ($withCreateDir && !file_exists($filePath) && !mkdir($filePath, 0775, true) && !is_dir($filePath)) {
50 1
            throw new \RuntimeException(sprintf('Directory "%s" was not created', $filePath));
51
        }
52 8
        $filePath .= DIRECTORY_SEPARATOR . $category . '.php';
53
54 8
        return $filePath;
55
    }
56
57 6
    private function read(string $category, string $locale): void
58
    {
59 6
        $path = $this->getFilePath($category, $locale);
60
61 6
        if (is_file($path)) {
62 5
            $messages = include $path;
63
64 5
            if (!\is_array($messages)) {
65 5
                throw new \RuntimeException('Invalid file format: ' . $path);
66
            }
67
        } else {
68 1
            $messages = [];
69
        }
70
71 6
        $this->messages[$category][$locale] = $messages;
72 6
    }
73
74 11
    public function write(string $category, string $locale, array $messages): void
75
    {
76 11
        $content = $this->generateMessagesFileContent($messages);
77
78 8
        $path = $this->getFilePath($category, $locale, true);
79
80 7
        if (file_put_contents($path, $content, LOCK_EX) === false) {
81 1
            throw new \RuntimeException('Can not write to ' . $path);
82
        }
83 7
    }
84
85 11
    private function generateMessagesFileContent(array $messages): string
86
    {
87 11
        $content = "<?php\nreturn ";
88 11
        if (empty($messages)) {
89 3
            $content .= '[]';
90
        } else {
91 8
            $content .= $this->messagesToCode($messages);
92 5
            $content .= ';';
93
        }
94 8
        $content .= "\n";
95
96 8
        return $content;
97
    }
98
99 8
    private function messagesToCode(array $messages): string
100
    {
101 8
        $code = '[';
102 8
        foreach ($messages as $messageId => $messageData) {
103 8
            if (!array_key_exists('message', $messageData)) {
104 1
                throw new InvalidArgumentException("Message is not valid for ID \"$messageId\". \"message\" key is missing.");
105
            }
106
107 7
            if (!is_string($messageData['message'])) {
108 1
                throw new InvalidArgumentException("Message is not a string for ID \"$messageId\".");
109
            }
110
111 6
            if (array_key_exists('comment', $messageData)) {
112 4
                if (!is_string($messageData['comment'])) {
113 1
                    throw new InvalidArgumentException("Message comment is not a string for ID \"$messageId\".");
114
                }
115
116 3
                $code .= "\n" . '    /* ' . $messageData['comment'] . ' */';
117
            }
118
119 5
            $code .= "\n" . '    ';
120 5
            $code .= "'{$messageId}'";
121 5
            $code .= ' => ';
122 5
            $code .= "'{$messageData['message']}'";
123 5
            $code .= ',';
124
        }
125 5
        $code .= "\n" . ']';
126 5
        return $code;
127
    }
128
}
129