Completed
Push — master ( 043413...7c943a )
by Mārtiņš
01:36
created

MessageExtractor::getExtractor()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
4
namespace Printful\GettextCms;
5
6
7
use Gettext\Extractors\Extractor;
8
use Gettext\Extractors\JsCode;
9
use Gettext\Extractors\PhpCode;
10
use Gettext\Extractors\VueJs;
11
use Gettext\Translations;
12
use League\Flysystem\Adapter\Local;
13
use League\Flysystem\Filesystem;
14
use League\Flysystem\Plugin\ListFiles;
15
use Printful\GettextCms\Exceptions\GettextCmsException;
16
use Printful\GettextCms\Exceptions\InvalidPathException;
17
use Printful\GettextCms\Exceptions\UnknownExtractorException;
18
use Printful\GettextCms\Structures\ScanItem;
19
20
class MessageExtractor
21
{
22
    const EXTRACTORS = [
23
        'js' => JsCode::class,
24
        'vue' => VueJs::class,
25
        'php' => PhpCode::class,
26
    ];
27
28
    /**
29
     * @param ScanItem[] $items
30
     * @param bool $defaultDomain Should we scan for translations in default domain (no domain messages)
31
     * @param array $otherDomains List of domains we should search (excluding the default domain
32
     * @return Translations[] List of translation files for each domain we wanted to extract
33
     * @throws GettextCmsException
34
     */
35
    public function extract(array $items, bool $defaultDomain = true, array $otherDomains = [])
36
    {
37
        $pathnames = $this->resolvePathnames($items);
38
39
        if ($defaultDomain) {
40
            // If we search for default domain, add an empty domain string
41
            $otherDomains[] = '';
42
        }
43
44
        $translations = [];
45
46
        foreach ($otherDomains as $domain) {
47
            $translations[] = $this->extractForDomain($domain, $pathnames);
48
        }
49
50
        return $translations;
51
    }
52
53
    /**
54
     * @param string $domain
55
     * @param array $pathnames
56
     * @return Translations
57
     * @throws UnknownExtractorException
58
     */
59
    private function extractForDomain($domain, array $pathnames)
60
    {
61
        $translations = new Translations;
62
        $translations->setDomain($domain);
63
64
        foreach ($pathnames as $pathname) {
65
            $this->extractFileMessages($pathname, $translations);
66
        }
67
68
        return $translations;
69
    }
70
71
    /**
72
     * @param $pathname
73
     * @param Translations $translations
74
     * @throws UnknownExtractorException
75
     */
76
    private function extractFileMessages($pathname, Translations $translations)
77
    {
78
        $extractor = $this->getExtractor($pathname);
79
80
        $extractor::fromFile($pathname, $translations);
81
    }
82
83
    /**
84
     * @param ScanItem[] $items
85
     * @return array Pathnames to matching files
86
     */
87
    public function resolvePathnames(array $items): array
88
    {
89
        return array_reduce($items, function (&$carry, ScanItem $item) {
90
            $carry = array_merge($carry, $this->resolveSingleItemFiles($item));
91
            return $carry;
92
        }, []);
93
    }
94
95
    /**
96
     * Returns a list of files that match this item
97
     *
98
     * @param ScanItem $item
99
     * @return array List of matching pathnames
100
     * @throws InvalidPathException
101
     */
102
    private function resolveSingleItemFiles(ScanItem $item): array
103
    {
104
        if (is_file($item->path)) {
105
            return [$item->path];
106
        }
107
108
        if (!is_dir($item->path)) {
109
            throw new InvalidPathException('Path "' . $item->path . '" does not exist');
110
        }
111
112
        return $this->resolveDirectoryFiles($item);
113
    }
114
115
    /**
116
     * @param ScanItem $item
117
     * @return string[] List of pathnames to files
118
     */
119
    private function resolveDirectoryFiles(ScanItem $item)
120
    {
121
        $dir = realpath($item->path);
122
123
        $adapter = new Local($dir);
124
        $filesystem = new Filesystem($adapter);
125
        $filesystem->addPlugin(new ListFiles);
126
127
        $files = $filesystem->listFiles('', $item->recursive);
128
129
        // If extensions are set, filter other files out
130
        if ($item->extensions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $item->extensions of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
131
            $files = array_filter($files, function ($file) use ($item) {
132
                return in_array($file['extension'], $item->extensions);
133
            });
134
        }
135
136
        return array_map(function ($file) use ($dir) {
137
            return $dir . DIRECTORY_SEPARATOR . $file['path'];
138
        }, $files);
139
    }
140
141
    /**
142
     * @param string $pathname Full path to file
143
     * @return Extractor
144
     * @throws UnknownExtractorException
145
     */
146
    private function getExtractor($pathname)
147
    {
148
        $extension = pathinfo($pathname, PATHINFO_EXTENSION);
149
150
        if (isset(self::EXTRACTORS[$extension])) {
151
            return self::EXTRACTORS[$extension];
152
        }
153
154
        throw new UnknownExtractorException('Extractor is not know for file extension "' . $extension . '"');
155
    }
156
}