Completed
Push — master ( b453a3...b1e9d6 )
by Ruud
40:05 queued 27:14
created

Importer::importSingleTranslation()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4.0119

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 10
cts 11
cp 0.9091
rs 9.568
c 0
b 0
f 0
cc 4
nc 4
nop 6
crap 4.0119
1
<?php
2
3
namespace Kunstmaan\TranslatorBundle\Service\Command\Importer;
4
5
use Box\Spout\Common\Type;
6
use Box\Spout\Reader\ODS\Sheet;
7
use Box\Spout\Reader\ReaderFactory;
8
use Kunstmaan\TranslatorBundle\Service\TranslationGroupManager;
9
use Symfony\Component\Console\Exception\LogicException;
10
use Symfony\Component\HttpFoundation\File\File;
11
use Symfony\Component\Translation\Loader\LoaderInterface;
12
13
class Importer
14
{
15
    /**
16
     * @var array
17
     */
18
    private $loaders = [];
19
20
    /**
21
     * @var TranslationGroupManager
22
     */
23
    private $translationGroupManager;
24
25 7
    public function __construct(TranslationGroupManager $translationGroupManager)
26
    {
27 7
        $this->translationGroupManager = $translationGroupManager;
28 7
    }
29
30 3
    public function import(\Symfony\Component\Finder\SplFileInfo $file, $force = false)
31
    {
32 3
        if (!is_array($this->loaders) || count($this->loaders) <= 0) {
33
            throw new \Exception('No translation file loaders tagged.');
34
        }
35
36 3
        $filename = $file->getFilename();
37 3
        list($domain, $locale, $extension) = explode('.', $filename);
38
39 3
        if (!isset($this->loaders[$extension]) || !$this->loaders[$extension] instanceof \Symfony\Component\Translation\Loader\LoaderInterface) {
40
            throw new \Exception(sprintf('Requested loader for extension .%s isnt set', $extension));
41
        }
42
43 3
        $loader = $this->loaders[$extension];
44 3
        $messageCatalogue = $loader->load($file->getPathname(), $locale, $domain);
45 3
        $importedTranslations = 0;
46
47 3
        $this->translationGroupManager->pullDBInMemory();
48
49 3
        foreach ($messageCatalogue->all($domain) as $keyword => $text) {
50 3
            if ($this->importSingleTranslation($keyword, $text, $locale, $filename, $domain, $force)) {
51 3
                ++$importedTranslations;
52
            }
53
        }
54
55 3
        $this->translationGroupManager->flushAndClearDBFromMemory();
56
57 3
        return $importedTranslations;
58
    }
59
60
    /**
61
     * @param string $file
62
     * @param array  $locales
63
     * @param bool   $force
64
     *
65
     * @return int
66
     *
67
     * @throws \Box\Spout\Common\Exception\IOException
68
     * @throws \Box\Spout\Common\Exception\UnsupportedTypeException
69
     * @throws \Box\Spout\Reader\Exception\ReaderNotOpenedException
70
     */
71
    public function importFromSpreadsheet(string $file, array $locales, $force = false)
72
    {
73
        $filePath = realpath(dirname($file)).DIRECTORY_SEPARATOR;
74
        $fileName = basename($file);
75
        $file = $filePath.$fileName;
76
77
        $this->translationGroupManager->pullDBInMemory();
78
79
        if (!file_exists($file)) {
80
            throw new LogicException(sprintf('Can not find file in %s', $file));
81
        }
82
83
        $format = (new File($file))->guessExtension();
84
        if (!\in_array($format, [Type::CSV, Type::ODS, Type::XLSX], true)) {
85
            $format = Type::CSV;
86
        }
87
88
        $headers = ['domain', 'keyword'];
89
        $locales = array_map('strtolower', $locales);
90
        $requiredHeaders = array_merge($headers, $locales);
91
92
        try {
93
            $reader = ReaderFactory::create($format);
94
            $reader->open($file);
95
        } catch (\Exception $e) {
96
            throw new LogicException('Format has to be either xlsx, ods or cvs');
97
        }
98
        $sheets = $reader->getSheetIterator();
99
100
        /** @var Sheet $sheet */
101
        $importedTranslations = 0;
102
        foreach ($sheets as $sheet) {
103
            $rows = $sheet->getRowIterator();
104
            $headers = [];
105
106
            /** @var array $row */
107
            foreach ($rows as $row) {
108
                if (empty($headers)) {
109
                    $headers = $row;
110
                    $headers = array_map('strtolower', $headers);
111
                    foreach ($requiredHeaders as $header) {
112
                        if (!\in_array($header, $headers)) {
113
                            throw new LogicException(sprintf('Header: %s, should be present in the file!', $header));
114
                        }
115
                    }
116
117
                    continue;
118
                }
119
                $domain = $row[array_search('domain', $headers)];
120
                $keyword = $row[array_search('keyword', $headers)];
121
                foreach ($locales as $locale) {
122
                    $this->importSingleTranslation($keyword, $row[array_search($locale, $headers)], $locale, $file, $domain, $force);
123
                    ++$importedTranslations;
124
                }
125
            }
126
127
            break;
128
        }
129
        $reader->close();
130
131
        $this->translationGroupManager->flushAndClearDBFromMemory();
132
133
        return $importedTranslations;
134
    }
135
136
    /**
137
     * @param      $keyword
138
     * @param      $text
139
     * @param      $locale
140
     * @param      $filename
141
     * @param      $domain
142
     * @param bool $force
143
     *
144
     * @return bool
145
     */
146 3
    private function importSingleTranslation($keyword, $text, $locale, $filename, $domain, $force = false)
147
    {
148 3
        if (strlen($keyword) > 255) {
149
            return false;
150
        }
151
152 3
        $translationGroup = $this->translationGroupManager->getTranslationGroupByKeywordAndDomain($keyword, $domain);
153
154 3
        if (!$translationGroup->hasTranslation($locale)) {
155 3
            $this->translationGroupManager->addTranslation($translationGroup, $locale, $text, $filename);
156
157 3
            return true;
158
        }
159
160 3
        if (true === $force) {
161 1
            $this->translationGroupManager->updateTranslation($translationGroup, $locale, $text, $filename);
162
163 1
            return true;
164
        }
165
166 2
        return false;
167
    }
168
169
    /**
170
     * Adds a loader to the translation importer.
171
     *
172
     * @param string          $format The format of the loader
173
     * @param LoaderInterface $loader
174
     */
175 7
    public function addLoader($format, LoaderInterface $loader)
176
    {
177 7
        $this->loaders[$format] = $loader;
178 7
    }
179
}
180