Passed
Push — master ( 988f4e...b3bcb6 )
by Alexander
06:25
created

Translator::guessLocale()   B

Complexity

Conditions 6
Paths 12

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.439
c 0
b 0
f 0
cc 6
eloc 14
nc 12
nop 1
1
<?php
2
3
/**
4
 * Translator
5
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
Coding Style introduced by
Missing @link tag in file comment
Loading history...
6
namespace Hokan22\LaravelTranslator;
7
8
use Hokan22\LaravelTranslator\Handler\DatabaseHandler;
9
use Hokan22\LaravelTranslator\Handler\DefaultHandler;
10
use Hokan22\LaravelTranslator\Handler\TranslationNotFoundException;
11
use Hokan22\LaravelTranslator\Models\TranslationIdentifier;
12
use Illuminate\Support\Facades\Config;
13
use Illuminate\Support\Facades\Log;
14
use Symfony\Component\Translation\Exception\NotFoundResourceException;
15
16
17
/**
18
 * Class Translator
19
 *
20
 * @package  Hokan22\LaravelTranslator
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 2
Loading history...
21
 * @author   Alexander Viertel <[email protected]>
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 3
Loading history...
22
 * @license  http://opensource.org/licenses/MIT MIT
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 2
Loading history...
23
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
24
class Translator
25
{
26
    /** @var array|HandlerInterface[] $aHandler Class to Handle the Translation defined in config */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
27
    protected $aHandler = [];
28
    /** @var string $locale The locale to translate to  */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
29
    protected $locale = '';
30
    /** @var string $group The translation group */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
31
    protected $group = 'default';
32
    /** @var string $configName The name of the config file */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
33
    protected $configName = 'translator';
34
    /** @var array $config Config cache */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
35
    protected $config;
36
37
    /**
38
     * Translator constructor.
39
     *
40
     * @param string $locale The locale to translate to
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
41
     * @throws \Exception
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
42
     */
43
    public function __construct($locale = '')
44
    {
45
        $this->config = Config::get($this->configName);
46
47
        $this->setLocale($locale);
48
    }
49
50
    /**
51
     * Return the config value for given key
52
     *
53
     * @param string $key Key for the config value to get
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
54
     * @return string|array Config value for $key
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
55
     */
56
    public function getConfigValue($key)
57
    {
58
        return $this->config[$key];
59
    }
60
61
    /**
62
     * Actual translate function
63
     * $parameter and $locale are optional
64
     *
65
     * @param string $identifier The identifier of the translation
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
66
     * @param array|null $parameters The parameters to inject into the translation
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
67
     * @param string $locale The locale to which to translate to overrides the class location for one translation
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 5 spaces after parameter name; 1 found
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
68
     * @throws \Exception
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
69
     * @return string Returns the translation with replaced parameters
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
70
     *
71
     */
0 ignored issues
show
Coding Style introduced by
Additional blank lines found at end of doc comment
Loading history...
72
    public function translate($identifier, $parameters = null, $locale = null)
73
    {
74
        if ($locale !== null) {
75
            $locale = $this->validateLocale($locale);
76
        } else {
77
            $locale = $this->locale;
78
        }
79
80
        if (!isset($this->aHandler[$locale])) {
81
            $this->aHandler[$locale] = $this->createHandler($locale);
82
        }
83
84
        try {
85
            $translation = $this->aHandler[$locale]->getTranslation($identifier, $this->group);
86
        } catch (NotFoundResourceException $exception) {
87
            // Thrown when the Identifier wasn't found
88
            $this->log($exception, 'error');
89
90
            if ($this->config['listening_enabled'] === true) {
91
                $this->addMissingIdentifierToDB($identifier, $parameters, 'default');
92
            }
93
94
            $translation = $this->returnMissingTranslation($identifier, $locale);
95
96
        } catch (TranslationNotFoundException $exception) {
97
            // Thrown when no translation for the locale was found
98
            $this->log($exception, 'error');
99
100
            $translation = $this->returnMissingTranslation($identifier, $locale);
101
        }
102
103
        if (is_array($parameters)) {
104
            $translation = $this->replaceParameter($translation, $parameters);
105
        }
106
107
        if (session('translation_live_mode')) {
108
            $id = $this->aHandler[$locale]->getDatabaseID($identifier);
109
            $translation = $this->addLiveModeLink($translation, $id);
110
        }
111
112
        // Return the translation
113
        return $translation;
114
    }
115
116
    /**
117
     * Inject a Link to the edit page into the translation
118
     *
119
     * @param string $translation
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
120
     * @param integer $id
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
121
     * @return string
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
122
     */
123
    public function addLiveModeLink($translation, $id) {
0 ignored issues
show
Coding Style introduced by
Opening brace should be on a new line
Loading history...
124
125
        $route = route('translator.admin.edit', ['id' => $id]);
126
127
        $inject = "<translation-anchor onclick='window.open(\"$route\", \"_blank\")' style='position: absolute; z-index: 999; cursor: pointer;'>&#9875;</translation-anchor>";
128
129
        $translation = "$translation $inject";
130
131
        return $translation;
132
    }
133
134
     /**
0 ignored issues
show
Coding Style introduced by
Doc comment for parameter "$locale" missing
Loading history...
135
      * Sets the Handler
136
      *
137
      * @param $locale
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
138
      * @return DefaultHandler
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
139
      */
140
    protected function createHandler($locale)
141
    {
142
        $handler_class = $this->config['handler'];
143
144
        if (session('translation_live_mode')) {
145
            $handler_class = DatabaseHandler::class;
146
        }
147
148
        try {
149
            $oHandler = new $handler_class($locale);
150
151
        } catch (\Exception $exception) {
152
153
            $this->log($exception, 'error');
154
            $this->log('Falling back to DatabaseHandler', 'warning');
155
156
            $oHandler = new DefaultHandler($locale);
157
        }
158
159
        return $oHandler;
160
    }
161
162
    /**
163
     * Set the locale to use in translations
164
     *
165
     * @param string $locale The locale to use
166
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
167
    public function setLocale($locale)
168
    {
169
        $locale = $this->validateLocale($locale);
170
171
        if (!isset($this->aHandler[$locale])) {
172
            $this->aHandler[$locale] = $this->createHandler($locale);
173
        }
174
175
        $this->locale = $locale;
176
    }
177
178
    /**
179
     * Add the missing identifier to the texts table in the database
180
     *
181
     * @param string $identifier The identifier to add to the db
182
     * @param array $parameters The parameters available for the translation
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
183
     * @param string $group The group to put the identifier in
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter name; 1 found
Loading history...
184
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
185
    public function addMissingIdentifierToDB($identifier, $parameters, $group)
186
    {
187
        if (!$this->hasIdentifier($identifier)) {
188
189
            $keys = [];
190
            if (is_array($parameters)) {
0 ignored issues
show
introduced by
The condition is_array($parameters) is always true.
Loading history...
191
                foreach($parameters as $key => $value) {
0 ignored issues
show
Coding Style introduced by
Expected "foreach (...) {\n"; found "foreach(...) {\n"
Loading history...
192
                    $keys[] = $key;
193
                }
194
            }
195
196
            TranslationIdentifier::create(
197
                [
198
                    "identifier"    => $identifier,
199
                    "parameters"    => $keys,
200
                    "group"         => isset($group) ? $group : 'default',
201
                    "page_name"     => app()->runningInConsole() ? '' : substr(request()->getRequestUri(), 1),
0 ignored issues
show
introduced by
The method runningInConsole() does not exist on Illuminate\Container\Container. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

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

201
                    "page_name"     => app()->/** @scrutinizer ignore-call */ runningInConsole() ? '' : substr(request()->getRequestUri(), 1),
Loading history...
202
                ]
203
            );
204
205
            if (isset($this->aHandler[$this->locale])) {
206
                // When using file Cache, adding the Identifier to the Database will not add it to file Cache!
207
                $this->aHandler[$this->locale]->refreshCache();
208
            }
209
            $this->log('The translation string "'.$identifier.'" will be written to the Database', 'notice');
210
        } else {
211
            $this->log('The translation string "'.$identifier.'" is already in the Database!', 'warning');
212
        }
213
    }
214
215
    /**
216
     * Check if the identifier exists in the database
217
     *
218
     * @param string $identifier The identifier to check
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
219
     * @return boolean Returns true if the identifier was found
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
220
     */
221
    public function hasIdentifier($identifier)
222
    {
223
        return TranslationIdentifier::where('identifier', $identifier)->count() > 0;
224
    }
225
226
    /**
227
     * Replace the parameters in the translation
228
     *
229
     * @param string $translation The translation with the parameter tags
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
230
     * @param array $parameters The parameters which to inject in the translation
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
231
     * @return string Returns the translation which its parameters replaced
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
232
     *
233
     * @todo Make Prefix and Suffix configurable
234
     */
235
    protected function replaceParameter($translation, $parameters)
236
    {
237
        foreach ($parameters as $key => $parameter) {
238
            // If the string (e.g "{name}") is not specified within the "parameters" array it won't be replaced!
239
            $translation = str_replace("{".$key."}", $parameter, $translation);
240
        }
241
        return $translation;
242
    }
243
244
    /**
245
     * Return the translation identifier and the locale
246
     *
247
     * @param string $identifier The identifier which is missing
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
248
     * @param string $locale The locale of which the translation is missing
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 1 found
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
249
     * @throws \Exception
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
250
     * @return string The string to display instead of the translation
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
251
     */
252
    protected function returnMissingTranslation($identifier, $locale)
253
    {
254
        if (config('app.env') !== 'production') {
255
            return '&lt;'.$identifier.':'.$locale.'&gt;';
256
        }
257
        return $identifier;
258
    }
259
260
    /**
261
     * Checks if the given locale is in the available_locales array.
262
     * If not try to guess it or fall back to the default locale
263
     *
264
     * @param string $locale The locale to validate
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
265
     * @return string Returns the validated Locale
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
266
     */
267
    public function validateLocale($locale)
268
    {
269
        $avail_locales      = $this->config['available_locales'];
270
        $default_locale     = $this->config['default_locale'];
271
272
        if ($this->locale == $locale && $this->locale !== '') {
273
            return $locale;
274
        }
275
276
        if ($locale == null) {
277
            if (session()->get('locale') != '') {
278
                $locale = session()->get('locale');
279
            } else {
280
                return $default_locale;
281
            }
282
        }
283
284
        if (!in_array($locale, $avail_locales)) {
285
            $locale = $this->guessLocale($locale);
286
        }
287
288
        return $locale;
289
    }
290
291
    /**
292
     * Tries to match the locale to an available Locale
293
     * Else returns the default locale
294
     *
295
     * @param string $locale The locale to match
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
296
     * @throws NotFoundResourceException
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
297
     * @return string Returns the guessed Locale
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
298
     */
299
    private function guessLocale($locale)
0 ignored issues
show
Coding Style introduced by
Private method name "Translator::guessLocale" must be prefixed with an underscore
Loading history...
300
    {
301
        $avail_locales      = $this->config['available_locales'];
302
        $default_locale     = $this->config['default_locale'];
303
304
        $found_locales = [];
305
306
        foreach ($avail_locales as $avail_locale) {
307
            if (strpos($avail_locale, $locale) !== false){
0 ignored issues
show
Coding Style introduced by
Expected "if (...) {\n"; found "if (...){\n"
Loading history...
Coding Style introduced by
There must be a single space between the closing parenthesis and the opening brace of a multi-line IF statement; found 0 spaces
Loading history...
308
                $found_locales[] = $avail_locale;
309
            }
310
        }
311
312
        if (in_array($default_locale, $found_locales) || count($found_locales) == 0){
0 ignored issues
show
Coding Style introduced by
Expected "if (...) {\n"; found "if (...){\n"
Loading history...
Coding Style introduced by
There must be a single space between the closing parenthesis and the opening brace of a multi-line IF statement; found 0 spaces
Loading history...
313
            $message = 'Locale "'.$locale.'" was not found! Falling back to default locale "'.$default_locale.'"';
314
            $locale = $default_locale;
315
316
        } else {
317
            $message = 'Locale "'.$locale.'" was not found! Falling back to similar locale "'.$found_locales[0].'"';
318
            $locale = $found_locales[0];
319
        }
320
321
        if ($message !== '') $this->log($message, 'warning');
0 ignored issues
show
Coding Style introduced by
Inline control structures are discouraged
Loading history...
322
323
        return $locale;
324
    }
325
326
    /**
327
     * Returns all translation for the the given locale of the given group
328
     *
329
     * @param string $locale The locale of the translations to get
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
330
     * @param string $group The group of the translations to get
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
331
     * @return array|mixed Returns an array of all translation in the $locale from group $group
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
332
     */
333
    public function getAllTranslations($locale, $group)
334
    {
335
        if (!isset($this->aHandler[$locale])) {
336
            $this->aHandler[$locale] = $this->createHandler($locale);
337
        }
338
339
        return $this->aHandler[$locale]->getAllTranslations($group);
340
    }
341
342
    /**
343
     * Log the given exception or string $exception as type $log_type when config log_level is set to debug
344
     *
345
     * @param \Exception|string $exception The Exception to log
346
     * @param string $log_type The type of the log to write in the log file
0 ignored issues
show
Coding Style introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
347
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
348
    protected function log($exception, $log_type = 'notice')
349
    {
350
        if ($this->config['log_level'] !== 'debug') {
351
            return;
352
        }
353
354
        switch ($log_type) {
355
            case 'error':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
356
                Log::error($exception);
357
                break;
358
359
            case 'warning':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
360
                Log::warning($exception);
361
                break;
362
363
            case 'notice':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
364
            default :
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
365
                Log::notice($exception);
366
                break;
367
        }
368
    }
369
}