Passed
Push — master ( c19cb6...9c6d4f )
by Yannick
08:19
created

executeVueTranslationsUpdate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 8
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 15
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chamilo\CoreBundle\Migrations\Schema\V200;
6
7
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
8
use Doctrine\DBAL\Schema\Schema;
9
use SubLanguageManager;
10
use Symfony\Bundle\FrameworkBundle\Console\Application;
11
use Symfony\Component\Console\Input\ArrayInput;
12
use Symfony\Component\Console\Output\BufferedOutput;
13
14
use const FILE_APPEND;
15
16
final class Version20240122221400 extends AbstractMigrationChamilo
17
{
18
    public function getDescription(): string
19
    {
20
        return 'Migration of sublanguages and Vue translation updates.';
21
    }
22
23
    public function up(Schema $schema): void
24
    {
25
        // Default sublanguages to be excluded from the update.
26
        $defaultSubLanguages = ['ast', 'ast_ES', 'ca', 'ca_ES', 'eo', 'gl', 'qu', 'quz_PE', 'qu_PE', 'zh-TW', 'zh_TW', 'pt-BR', 'pt_PT', 'fur', 'fur_IT', 'oc', 'oc_FR'];
27
28
        // Fetching sublanguages from the database.
29
        $sql = "SELECT * FROM language WHERE parent_id IS NOT NULL AND isocode NOT IN('".implode("', '", $defaultSubLanguages)."')";
30
        $sublanguages = $this->connection->executeQuery($sql)->fetchAllAssociative();
31
32
        foreach ($sublanguages as $sublanguage) {
33
            $newIsoCode = $this->updateAndGenerateSubLanguage($sublanguage);
34
            $this->generatePoFileFromTrad4All($sublanguage['english_name'], $newIsoCode);
35
        }
36
37
        // Update Vue translations after processing all sublanguages.
38
        $this->executeVueTranslationsUpdate();
39
40
        // Delete the 'import' folder at the end of the process.
41
        // $this->deleteImportFolder();
42
    }
43
44
    private function updateAndGenerateSubLanguage(array $sublanguage): string
45
    {
46
        // Get the parent language ID
47
        $parentId = $sublanguage['parent_id'];
48
49
        // Query to obtain the isocode of the parent language
50
        $parentIsoQuery = 'SELECT isocode FROM language WHERE id = ?';
51
        $parentIsoCode = $this->connection->executeQuery($parentIsoQuery, [$parentId])->fetchOne();
52
53
        // Get the prefix of the parent language's isocode
54
        $firstIso = explode('_', $parentIsoCode)[0];
55
        $newIsoCode = $firstIso.'_'.$sublanguage['id'];
56
57
        // Update the isocode in the language table
58
        $updateLanguageQuery = 'UPDATE language SET isocode = ? WHERE id = ?';
59
        $this->connection->executeStatement($updateLanguageQuery, [$newIsoCode, $sublanguage['id']]);
60
        error_log('Updated language table for id '.$sublanguage['id']);
61
62
        // Check and update in settings
63
        $updateSettingsQuery = "UPDATE settings SET selected_value = ? WHERE variable = 'platform_language' AND selected_value = ?";
64
        $this->connection->executeStatement($updateSettingsQuery, [$newIsoCode, $sublanguage['english_name']]);
65
        error_log('Updated settings for language '.$sublanguage['english_name']);
66
67
        // Check and update in user table
68
        $updateUserQuery = 'UPDATE user SET locale = ? WHERE locale = ?';
69
        $this->connection->executeStatement($updateUserQuery, [$newIsoCode, $sublanguage['english_name']]);
70
        error_log('Updated user table for language '.$sublanguage['english_name']);
71
72
        // Check and update in course table
73
        $updateCourseQuery = 'UPDATE course SET course_language = ? WHERE course_language = ?';
74
        $this->connection->executeStatement($updateCourseQuery, [$newIsoCode, $sublanguage['english_name']]);
75
        error_log('Updated course table for language '.$sublanguage['english_name']);
76
77
        // Return the new ISO code.
78
        return $newIsoCode;
79
    }
80
81
    private function generatePoFileFromTrad4All(string $englishName, string $isocode): void
82
    {
83
        $kernel = $this->container->get('kernel');
0 ignored issues
show
Bug introduced by
The method get() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

83
        /** @scrutinizer ignore-call */ 
84
        $kernel = $this->container->get('kernel');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
84
        $updateRootPath = $this->getUpdateRootPath();
85
86
        $langPath = $updateRootPath.'/main/lang/'.$englishName.'/trad4all.inc.php';
87
        $destinationFilePath = $kernel->getProjectDir().'/var/translations/messages.'.$isocode.'.po';
88
        $originalFile = $updateRootPath.'/main/lang/english/trad4all.inc.php';
89
90
        if (!file_exists($langPath)) {
91
            error_log("Original file not found: $langPath");
92
93
            return;
94
        }
95
96
        $terms = SubLanguageManager::get_all_language_variable_in_file(
97
            $originalFile,
98
            true
99
        );
100
101
        foreach ($terms as $index => $translation) {
102
            $terms[$index] = trim(rtrim($translation, ';'), '"');
103
        }
104
105
        $header = 'msgid ""'."\n".'msgstr ""'."\n".
106
            '"Project-Id-Version: chamilo\n"'."\n".
107
            '"Language: '.$isocode.'\n"'."\n".
108
            '"Content-Type: text/plain; charset=UTF-8\n"'."\n".
109
            '"Content-Transfer-Encoding: 8bit\n"'."\n\n";
110
        file_put_contents($destinationFilePath, $header);
111
112
        $originalTermsInLanguage = SubLanguageManager::get_all_language_variable_in_file(
113
            $langPath,
114
            true
115
        );
116
117
        $termsInLanguage = [];
118
        foreach ($originalTermsInLanguage as $id => $content) {
119
            if (!isset($termsInLanguage[$id])) {
120
                $termsInLanguage[$id] = trim(rtrim($content, ';'), '"');
121
            }
122
        }
123
124
        $bigString = '';
125
        $doneTranslations = [];
126
        foreach ($terms as $term => $englishTranslation) {
127
            if (isset($doneTranslations[$englishTranslation])) {
128
                continue;
129
            }
130
            $doneTranslations[$englishTranslation] = true;
131
            $translatedTerm = $termsInLanguage[$term] ?? '';
132
133
            // Here we apply a little correction to avoid unterminated strings
134
            // when a string ends with a \"
135
            if (preg_match('/\\\$/', $englishTranslation)) {
136
                $englishTranslation .= '"';
137
            }
138
139
            $search = ['\{', '\}', '\(', '\)', '\;'];
140
            $replace = ['\\\{', '\\\}', '\\\(', '\\\)', '\\\;'];
141
            $englishTranslation = str_replace($search, $replace, $englishTranslation);
142
            if (preg_match('/\\\$/', $translatedTerm)) {
143
                $translatedTerm .= '"';
144
            }
145
            $translatedTerm = str_replace($search, $replace, $translatedTerm);
146
            if (empty($translatedTerm)) {
147
                continue;
148
            }
149
            // Now build the line
150
            $bigString .= 'msgid "'.$englishTranslation.'"'."\n".'msgstr "'.$translatedTerm.'"'."\n\n";
151
        }
152
        file_put_contents($destinationFilePath, $bigString, FILE_APPEND);
153
154
        error_log("Done generating gettext file in $destinationFilePath !\n");
155
    }
156
157
    private function executeVueTranslationsUpdate(): void
158
    {
159
        $application = new Application($this->container->get('kernel'));
160
        $application->setAutoExit(false);
161
162
        $input = new ArrayInput([
163
            'command' => 'chamilo:update_vue_translations',
164
        ]);
165
        $output = new BufferedOutput();
166
167
        $application->run($input, $output);
168
169
        $content = $output->fetch();
170
171
        error_log($content);
172
    }
173
174
    private function recursiveRemoveDirectory($directory): void
175
    {
176
        foreach (glob("{$directory}/*") as $file) {
177
            if (is_dir($file)) {
178
                $this->recursiveRemoveDirectory($file);
179
            } else {
180
                unlink($file);
181
            }
182
        }
183
        rmdir($directory);
184
    }
185
186
    public function down(Schema $schema): void {}
187
}
188