Completed
Push — 5.6 ( 679697...f4d50c )
by Jeroen
16:35 queued 10:49
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 bool $force
62
     *
63
     * @return int
64
     *
65
     * @throws \Box\Spout\Common\Exception\IOException
66
     * @throws \Box\Spout\Common\Exception\UnsupportedTypeException
67
     * @throws \Box\Spout\Reader\Exception\ReaderNotOpenedException
68
     */
69
    public function importFromSpreadsheet(string $file, array $locales, $force = false)
70
    {
71
        $filePath = realpath(\dirname($file)) . DIRECTORY_SEPARATOR;
72
        $fileName = basename($file);
73
        $file = $filePath . $fileName;
74
75
        $this->translationGroupManager->pullDBInMemory();
76
77
        if (!file_exists($file)) {
78
            throw new LogicException(sprintf('Can not find file in %s', $file));
79
        }
80
81
        $format = (new File($file))->guessExtension();
82
        if (!\in_array($format, [Type::CSV, Type::ODS, Type::XLSX], true)) {
83
            $format = Type::CSV;
84
        }
85
86
        $headers = ['domain', 'keyword'];
87
        $locales = array_map('strtolower', $locales);
88
        $requiredHeaders = array_merge($headers, $locales);
89
90
        try {
91
            $reader = ReaderFactory::create($format);
92
            $reader->open($file);
93
        } catch (\Exception $e) {
94
            throw new LogicException('Format has to be either xlsx, ods or cvs');
95
        }
96
        $sheets = $reader->getSheetIterator();
97
98
        /** @var Sheet $sheet */
99
        $importedTranslations = 0;
100
        foreach ($sheets as $sheet) {
101
            $rows = $sheet->getRowIterator();
102
            $headers = [];
103
104
            /** @var array $row */
105
            foreach ($rows as $row) {
106
                if (empty($headers)) {
107
                    $headers = $row;
108
                    $headers = array_map('strtolower', $headers);
109
                    foreach ($requiredHeaders as $header) {
110
                        if (!\in_array($header, $headers)) {
111
                            throw new LogicException(sprintf('Header: %s, should be present in the file!', $header));
112
                        }
113
                    }
114
115
                    continue;
116
                }
117
                $domain = $row[array_search('domain', $headers)];
118
                $keyword = $row[array_search('keyword', $headers)];
119
                foreach ($locales as $locale) {
120
                    $this->importSingleTranslation($keyword, $row[array_search($locale, $headers)], $locale, null, $domain, $force);
121
                    ++$importedTranslations;
122
                }
123
            }
124
125
            break;
126
        }
127
        $reader->close();
128
129
        $this->translationGroupManager->flushAndClearDBFromMemory();
130
131
        return $importedTranslations;
132
    }
133
134
    /**
135
     * @param      $keyword
136
     * @param      $text
137
     * @param      $locale
138
     * @param      $filename
139
     * @param      $domain
140
     * @param bool $force
141
     *
142
     * @return bool
143
     */
144 3
    private function importSingleTranslation($keyword, $text, $locale, $filename, $domain, $force = false)
145
    {
146 3
        if (\strlen($keyword) > 255) {
147
            return false;
148
        }
149
150 3
        $translationGroup = $this->translationGroupManager->getTranslationGroupByKeywordAndDomain($keyword, $domain);
151
152 3
        if (!$translationGroup->hasTranslation($locale)) {
153 3
            $this->translationGroupManager->addTranslation($translationGroup, $locale, $text, $filename);
154
155 3
            return true;
156
        }
157
158 3
        if (true === $force) {
159 1
            $this->translationGroupManager->updateTranslation($translationGroup, $locale, $text, $filename);
160
161 1
            return true;
162
        }
163
164 2
        return false;
165
    }
166
167
    /**
168
     * Adds a loader to the translation importer.
169
     *
170
     * @param string $format The format of the loader
171
     */
172 7
    public function addLoader($format, LoaderInterface $loader)
173
    {
174 7
        $this->loaders[$format] = $loader;
175 7
    }
176
}
177