Passed
Push — master ( f28c2c...dc352d )
by Alexander
02:05
created

Extractor::applyRoot()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 12
ccs 7
cts 7
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\TranslatorExtractor;
6
7
use Symfony\Component\Console\Output\OutputInterface;
8
use Yiisoft\Files\PathMatcher\PathMatcher;
9
use Yiisoft\Translator\Extractor\TranslationExtractor;
10
use Yiisoft\TranslatorExtractor\Exception\NoCategorySourceConfigException;
11
12
/**
13
 * Extracts translator IDs from files within a given path and writes them into message source given merging
14
 * results with what is already there.
15
 */
16
final class Extractor
17
{
18
    /** @var string[]|null */
19
    private ?array $except = ['./vendor/**'];
20
21
    /** @var string[]|null */
22
    private ?array $only = null;
23
24
    /**
25
     * @var CategorySource[] Array of category message sources indexed by category names.
26
     */
27
    private array $categorySources = [];
28
29
    /**
30
     * @param CategorySource[] $categories
31
     */
32 18
    public function __construct(array $categories)
33
    {
34 18
        if (empty($categories)) {
35 2
            throw new NoCategorySourceConfigException();
36
        }
37
38 16
        foreach ($categories as $category) {
39 16
            $this->categorySources[$category->getName()] = $category;
40
        }
41 16
    }
42
43
    /**
44
     * Set list of patterns that the files or directories should not match.
45
     *
46
     * @see PathMatcher
47
     *
48
     * @param string[] $except
49
     */
50 9
    public function setExcept(array $except): void
51
    {
52 9
        if (!empty($except)) {
53 3
            $this->except = $except;
54
        }
55 9
    }
56
57
    /**
58
     * Set list of patterns that the files or directories should match.
59
     *
60
     * @see PathMatcher
61
     *
62
     * @param string[] $only
63
     */
64 9
    public function setOnly(array $only): void
65
    {
66 9
        if (!empty($only)) {
67 3
            $this->only = $only;
68
        }
69 9
    }
70
71
    /**
72
     * @param string $filesPath Path to files to extract from.
73
     * @param string $defaultCategory Category to use if category isn't set in translation call.
74
     * @param string[] $languages Languages to write extracted IDs to.
75
     * @param OutputInterface $output
76
     */
77 16
    public function process(string $filesPath, string $defaultCategory, array $languages, OutputInterface $output): void
78
    {
79 16
        if (!isset($this->categorySources[$defaultCategory])) {
80 1
            $output->writeln('<comment>Default category was not found in a list of Categories.</comment>');
81 1
            return;
82
        }
83
84 15
        $translationExtractor = new TranslationExtractor(
85 15
            $filesPath,
86 15
            $this->applyRoot($this->only, $filesPath),
87 15
            $this->applyRoot($this->except, $filesPath)
88
        );
89
90 15
        $messagesList = $translationExtractor->extract($defaultCategory);
91
92 15
        if (empty($messagesList)) {
93 6
            $output->writeln('<comment>Messages not found</comment>');
94 6
            return;
95
        }
96
97 9
        $output->writeln('Languages: ' . implode(', ', $languages));
98
99
        /**
100
         * @var string $categoryName
101
         * @var array<array-key, array<string, string>|mixed> $messages
102
         */
103 9
        foreach ($messagesList as $categoryName => $messages) {
104 9
            $output->writeln('<info>Category: "' . $categoryName . '", messages found: ' . count($messages) . '.</info>');
105
106
            /** @var array<string, array<string, string>> $convertedMessages */
107 9
            $convertedMessages = $this->convert($messages);
108 9
            foreach ($languages as $language) {
109 9
                $extractCategory = isset($this->categorySources[$categoryName]) ? $categoryName : $defaultCategory;
110 9
                $this->addMessages($extractCategory, $language, $convertedMessages);
111
            }
112
        }
113 9
    }
114
115 9
    private function addMessages(string $categoryName, string $language, array $messages): void
116
    {
117 9
        $readMessages = $this->categorySources[$categoryName]->readMessages($categoryName, $language);
118
        /** @var array<string, array<string, string>> $convertedMessages */
119 9
        $convertedMessages = array_merge($messages, $readMessages);
120 9
        $this->categorySources[$categoryName]->writeMessages($categoryName, $language, $convertedMessages);
121 9
    }
122
123 9
    private function convert(array $messages): array
124
    {
125 9
        $returningMessages = [];
126
127
        /** @var array<string, string> $messages */
128 9
        foreach ($messages as $message) {
129 9
            $returningMessages[$message] = ['message' => $message];
130
        }
131
132 9
        return $returningMessages;
133
    }
134
135
    /**
136
     * @param string[]|null $list
137
     * @param string $rootFolder
138
     *
139
     * @return string[]|null
140
     */
141 15
    private function applyRoot(?array $list, string $rootFolder): ?array
142
    {
143 15
        if (is_array($list)) {
0 ignored issues
show
introduced by
The condition is_array($list) is always true.
Loading history...
144 15
            return array_map(
145 15
                static function (string $except) use ($rootFolder): string {
146 15
                    return preg_replace('#^\./#', $rootFolder . '/', $except);
147 15
                },
148
                $list
149
            );
150
        }
151
152 12
        return $list;
153
    }
154
}
155