Passed
Push — master ( fd31ea...8a1c29 )
by Fran
09:11
created

CustomTranslateExtension::translationsCheckLoad()   F

Complexity

Conditions 17
Paths 240

Size

Total Lines 54
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 32
CRAP Score 20.901

Importance

Changes 0
Metric Value
cc 17
eloc 42
c 0
b 0
f 0
nc 240
nop 3
dl 0
loc 54
ccs 32
cts 42
cp 0.7619
crap 20.901
rs 3.8833

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace PSFS\base\extension;
4
5
use PSFS\base\config\Config;
6
use PSFS\base\Logger;
7
use PSFS\base\Security;
8
use PSFS\base\types\helpers\I18nHelper;
9
use PSFS\base\types\helpers\Inspector;
10
use PSFS\base\types\traits\SingletonTrait;
11
use Twig\Extension\AbstractExtension;
12
use Twig\TokenParser\BlockTokenParser;
13
use Twig\TwigFilter;
14
15
/**
16
 * Class CustomTranslateExtension
17
 * @package PSFS\base\extension
18
 */
19
class CustomTranslateExtension extends AbstractExtension
20
{
21
    use SingletonTrait;
22
23
    const CUSTOM_LOCALE_SESSION_KEY = '__PSFS_CUSTOM_LOCALE_KEY__';
24
    const LOCALE_CACHED_VERSION = '__PSFS_LOCALE_VERSION__';
25
    const LOCALE_CACHED_TAG = '__PSFS_TRANSLATIONS__';
26
27
    /**
28
     * @var array
29
     */
30
    protected static $translations = [];
31
32
    /**
33
     * @var array
34
     */
35
    protected static $translationsKeys = [];
36
    /**
37
     * @var string
38
     */
39
    protected static $locale = 'es_ES';
40
    /**
41
     * @var bool
42
     */
43
    protected static $generate = false;
44
    /**
45
     * @var string
46
     */
47
    protected static $filename = '';
48
49
    /**
50
     * @return array|mixed
51
     */
52 2
    protected static function extractBaseTranslations($locale = null)
53
    {
54 2
        $locale = $locale ?? self::$locale;
55
        // Gather always the base translations
56 2
        $standardTranslations = [];
57 2
        self::$filename = implode(DIRECTORY_SEPARATOR, [LOCALE_DIR, 'custom', $locale . '.json']);
58 2
        if (file_exists(self::$filename)) {
59 2
            $standardTranslations = json_decode(file_get_contents(self::$filename), true);
60
        }
61 2
        return $standardTranslations;
62
    }
63
64
    /**
65
     * @param string $locale
66
     * @return void
67
     */
68 2
    protected static function generateTranslationsKeys($locale) {
69 2
        self::$translationsKeys[$locale] = [];
70 2
        foreach(self::$translations[$locale] as $key => $value) {
71 2
            $tKey = mb_convert_case($key, MB_CASE_LOWER, "UTF-8");
72 2
            self::$translationsKeys[$locale][$tKey] = $key;
73
        }
74
    }
75
76
    /**
77
     * @param string $customKey
78
     * @param bool $forceReload
79
     * @param bool $useBase
80
     */
81 2
    protected static function translationsCheckLoad($customKey = null, $forceReload = false, $useBase = false)
82
    {
83 2
        Inspector::stats('[translationsCheckLoad] Start checking translations load', Inspector::SCOPE_DEBUG);
84 2
        $session = Security::getInstance();
85 2
        $session_locale = $session->getSessionKey(I18nHelper::PSFS_SESSION_LOCALE_KEY) ?? $session->getSessionKey(I18nHelper::PSFS_SESSION_LANGUAGE_KEY);
86 2
        self::$locale = $forceReload ? $session_locale : I18nHelper::extractLocale($session_locale);
87 2
        $locale = self::$locale;
88 2
        $version = $session->getSessionKey(self::LOCALE_CACHED_VERSION);
89 2
        $configVersion = self::$locale . '_' . Config::getParam('cache.var', 'v1');
90 2
        if ($forceReload) {
91 1
            Inspector::stats('[translationsCheckLoad] Force translations reload', Inspector::SCOPE_DEBUG);
92 1
            self::dropInstance();
93 1
            $version = null;
94 1
            self::$translations[self::$locale] = [];
95
        }
96 2
        if((!array_key_exists($locale, self::$translations) || count(self::$translations[$locale]) === 0) && strlen($locale) === 2) {
97
            $locale = $locale . '_' . strtoupper($locale);
98
            if(array_key_exists($locale, self::$translations)) {
99
                self::$translations[self::$locale] = self::$translations[$locale];
100
                self::generateTranslationsKeys(self::$locale);
101
            }
102
        }
103 2
        if(!array_key_exists($locale, self::$translations) || count(self::$translations[$locale]) === 0) {
104 2
            Inspector::stats('[translationsCheckLoad] Extracting translations', Inspector::SCOPE_DEBUG);
105 2
            self::$generate = (boolean)Config::getParam('i18n.autogenerate', false);
106 2
            if(null !== $version && $version === $configVersion) {
107
                Inspector::stats('[translationsCheckLoad] Translations loaded from session', Inspector::SCOPE_DEBUG);
108
                self::$translations = $session->getSessionKey(self::LOCALE_CACHED_TAG);
109
            } else {
110 2
                if (!$useBase) {
111 2
                    $customKey = $customKey ?: $session->getSessionKey(self::CUSTOM_LOCALE_SESSION_KEY);
112
                }
113 2
                $standardTranslations = self::extractBaseTranslations();
114
                // If the project has custom translations, gather them
115 2
                if (null !== $customKey) {
116
                    Logger::log('[' . self::class . '] Custom key detected: ' . $customKey, LOG_INFO);
117
                    self::$filename = implode(DIRECTORY_SEPARATOR, [LOCALE_DIR, 'custom', $customKey, $locale . '.json']);
118 2
                } elseif (!empty($standardTranslations)) {
119 2
                    self::$translations[$locale] = $standardTranslations;
120 2
                    self::generateTranslationsKeys($locale);
121
                }
122
                // Finally we merge base and custom translations to complete all the i18n set
123 2
                if (file_exists(self::$filename)) {
124 2
                    Logger::log('[' . self::class . '] Custom locale detected: ' . $customKey . ' [' . $locale . ']', LOG_INFO);
125 2
                    self::$translations[$locale] = array_merge($standardTranslations, json_decode(file_get_contents(self::$filename), true));
126 2
                    self::generateTranslationsKeys($locale);
127 2
                    $session->setSessionKey(self::LOCALE_CACHED_TAG, self::$translations);
128 2
                    $session->setSessionKey(self::LOCALE_CACHED_VERSION, $configVersion);
129
                } elseif (null !== $customKey) {
130
                    self::translationsCheckLoad(null, $forceReload, true);
131
                }
132
            }
133
        }
134 2
        Inspector::stats('[translationsCheckLoad] Translations loaded', Inspector::SCOPE_DEBUG);
135
    }
136
137
    /**
138
     * {@inheritdoc}
139
     */
140 1
    public function getTokenParsers()
141
    {
142 1
        return [new BlockTokenParser()];
143
    }
144
145
    /**
146
     * {@inheritdoc}
147
     */
148 2
    public function getFilters()
149
    {
150 1
        return array(
151 1
            new TwigFilter('trans', function ($message) {
152 2
                return self::_($message);
153 1
            }),
154 1
        );
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     */
160
    public function getName()
161
    {
162
        return 'PSFSi18n';
163
    }
164
165
    /**
166
     * @param $message
167
     * @param string $customKey
168
     * @param bool $forceReload
169
     * @return mixed|string
170
     */
171 12
    public static function _($message, $customKey = null, $forceReload = false)
172
    {
173 12
        if(0 === count(self::$translations) || $forceReload) {
174 2
            self::translationsCheckLoad($customKey, $forceReload);
175
        }
176
        // Set default translation to catch missing strings
177 12
        $isDebugMode = (bool)Config::getParam('debug', false);
178 12
        $translation = (bool)Config::getParam('debug', false) ? 'MISSING_TRANSLATION - ' . self::$locale : $message;
179
        // Check if the message is already translated ignoring the string case
180 12
        $key = mb_convert_case($message, MB_CASE_LOWER, "UTF-8");
181 12
        if(array_key_exists(self::$locale, self::$translationsKeys) && array_key_exists($key, self::$translationsKeys[self::$locale])) {
182 9
            $message = self::$translationsKeys[self::$locale][$key];
183
        }
184
        // Check if exists
185 12
        if (array_key_exists(self::$locale, self::$translations) && array_key_exists($message, self::$translations[self::$locale])) {
186 9
            $translation = self::$translations[self::$locale][$message];
187 4
        } else if(!$forceReload && !$isDebugMode) {
188
            $translation = gettext($message);
189
        }
190 12
        if (self::$generate) {
191
            self::generate($message, $translation);
192
        }
193 12
        return $translation;
194
    }
195
196
    /**
197
     * @param string $message
198
     * @param string $translation
199
     */
200
    protected static function generate($message, $translation)
201
    {
202
        if(!array_key_exists(self::$locale, self::$translations)) {
203
            self::$translations[self::$locale] = [];
204
            self::$translationsKeys[self::$locale] = [];
205
        }
206
        if (!array_key_exists($message, self::$translations)) {
207
            self::$translations[self::$locale][$message] = $translation;
208
            self::$translationsKeys[self::$locale][mb_convert_case($message, MB_CASE_LOWER, "UTF-8")] = $message;
209
        }
210
        file_put_contents(self::$filename, json_encode(array_unique(self::$translations), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
211
    }
212
}
213