Issues (238)

src/Services/Translation.php (35 issues)

1
<?php
2
3
namespace Translation\Services;
4
5
use ErrorException;
6
use Illuminate\Contracts\Foundation\Application;
7
use Illuminate\Database\Eloquent\Model;
8
use InvalidArgumentException;
9
use Translation\Contracts\Client as ClientInterface;
10
use Translation\Contracts\Translation as TranslationInterface;
11
use UnexpectedValueException;
12
use Exception;
13
use Carbon\Carbon;
14
use Illuminate\Support\Facades\Schema;
15
use Translation\Models\Language;
16
use Illuminate\Support\Facades\Auth;
17
use Muleta\Utils\Modificators\ArrayModificator;
18
use Illuminate\Support\Facades\Cache;
19
use Translation\Repositories\LangRepository;
20
use Translation\Repositories\LangResourcesRepository;
21
22
class Translation implements TranslationInterface
23
{
24
    /**
25
     * Holds the application locale.
26
     *
27
     * @var string
28
     */
29
    protected $locale = '';
30
31
    /**
32
     * Holds the locale model.
33
     *
34
     * @var Model
35
     */
36
    protected $localeModel;
37
38
    /**
39
     * Holds the translation model.
40
     *
41
     * @var Model
42
     */
43
    protected $translationModel;
44
45
    /**
46
     * Holds the translation client.
47
     *
48
     * @var ClientInterface
49
     */
50
    protected $client;
51
52
    /**
53
     * Holds the current cache instance.
54
     *
55
     * @var \Illuminate\Cache\CacheManager
0 ignored issues
show
The type Illuminate\Cache\CacheManager was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
56
     */
57
    protected $cache;
58
59
    /**
60
     * Holds the current config instance.
61
     *
62
     * @var \Illuminate\Config\Repository
0 ignored issues
show
The type Illuminate\Config\Repository was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
63
     */
64
    protected $config;
65
66
    /**
67
     * Holds the current request instance.
68
     *
69
     * @var \Illuminate\Http\Request
0 ignored issues
show
The type Illuminate\Http\Request was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
70
     */
71
    protected $request;
72
73
    /**
74
     * The default amount of time (minutes) to store the cached translations.
75
     *
76
     * @var int
77
     */
78
    private $cacheTime = 30;
79
80
    /**
81
     * {@inheritdoc}
82
     */
83
    public function __construct(Application $app)
84
    {
85
        $this->config = $app->make('config');
86
        $this->cache = $app->make('cache');
87
        $this->request = $app->make('request');
88
89
        $this->localeModel = $app->make($this->getConfigLocaleModel());
90
        $this->translationModel = $app->make($this->getConfigTranslationModel());
91
        $this->client = $app->make($this->getConfigClient());
92
93
        // Set the default locale to the current application locale
94
        $this->setLocale($this->getConfigDefaultLocale());
95
96
        // Set the cache time from the configuration
97
        $this->setCacheTime($this->getConfigCacheTime());
0 ignored issues
show
It seems like $this->getConfigCacheTime() can also be of type string; however, parameter $time of Translation\Services\Translation::setCacheTime() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

97
        $this->setCacheTime(/** @scrutinizer ignore-type */ $this->getConfigCacheTime());
Loading history...
98
    }
99
100
    /**
101
     * Pega um code e retorna corretamente translation e pais
102
     *
103
     * @return void
104
     */
105
    public function getCode($locale = null)
106
    {
107
        if (!is_null($locale)) {
108
            return $locale;
109
        }
110
        return $this->getActualLanguageCode();
111
    }
112
    public function getLanguageCode($locale = null)
113
    {
114
        return ArrayModificator::multiExplode(
115
            [
116
                '|',
117
                '_',
118
                '-'
119
            ],
120
            $this->getCode($locale)
0 ignored issues
show
Are you sure the usage of $this->getCode($locale) targeting Translation\Services\Translation::getCode() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
$this->getCode($locale) of type void is incompatible with the type string expected by parameter $stringToArray of Muleta\Utils\Modificator...ficator::multiExplode(). ( Ignorable by Annotation )

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

120
            /** @scrutinizer ignore-type */ $this->getCode($locale)
Loading history...
121
        )[0];
122
    }
123
124
    /**
125
     * 
126
     */
127
    public function getCountryCode($locale = null)
128
    {
129
        $explodeCode = ArrayModificator::multiExplode(
130
            [
131
                '|',
132
                '_',
133
                '-'
134
            ],
135
            $this->getCode($locale)
0 ignored issues
show
Are you sure the usage of $this->getCode($locale) targeting Translation\Services\Translation::getCode() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
$this->getCode($locale) of type void is incompatible with the type string expected by parameter $stringToArray of Muleta\Utils\Modificator...ficator::multiExplode(). ( Ignorable by Annotation )

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

135
            /** @scrutinizer ignore-type */ $this->getCode($locale)
Loading history...
136
        );
137
        if (!isset($explodeCode[1])) {
138
            return null;
139
        }
140
        return $explodeCode[1];
141
    }
142
143
    /**
144
     * {@inheritdoc}
145
     */
146
    public function translate($text = '', $replacements = [], $toLocale = '', bool $runOnce = false)
147
    {
148
        try {
149
            // Make sure $text is actually a string and not and object / int
150
            $this->validateText($text);
151
152
            // Get the default translation text. This will insert the translation
153
            // and the default application locale if they don't
154
            // exist using firstOrCreate
155
            $defaultTranslation = $this->getDefaultTranslation($text);
156
157
            // If there are replacements inside the array we need to convert them
158
            // into google translate safe placeholders. ex :name to __name__
159
            if (count($replacements) > 0) {
160
                $defaultTranslation->translation = $this->makeTranslationSafePlaceholders($text, $replacements);
161
            }
162
163
            // If a toLocale has been provided, we're only translating a single string, so
164
            // we won't call the getLocale method as it retrieves and sets the default
165
            // session locale. If it has not been provided, we'll get the
166
            // default locale, and set it on the current session.
167
            if ($toLocale != '') {
168
                $toLocale = $this->firstOrCreateLocale($toLocale);
169
            } else {
170
                $toLocale = $this->firstOrCreateLocale($this->getLocale());
171
            }
172
173
            // Check if translation is requested for default locale.
174
            // If it is default locale we can just return default translation.
175
            if ($defaultTranslation->getAttribute($this->localeModel->getForeignKey()) == $toLocale->getKey()) {
176
                return $this->makeReplacements($defaultTranslation->translation, $replacements);
0 ignored issues
show
It seems like $defaultTranslation->translation can also be of type Illuminate\Database\Eloq...uent\Relations\Relation and Illuminate\Database\Eloquent\Relations\Relation; however, parameter $text of Translation\Services\Tra...ion::makeReplacements() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

176
                return $this->makeReplacements(/** @scrutinizer ignore-type */ $defaultTranslation->translation, $replacements);
Loading history...
177
            }
178
179
            // Since we are not on default translation locale, we will have to
180
            // create (or get first) translation for provided locale where
181
            // parent translation is our default translation.
182
            $translation = $this->firstOrCreateTranslation(
183
                $toLocale,
184
                $defaultTranslation->translation,
0 ignored issues
show
It seems like $defaultTranslation->translation can also be of type Illuminate\Database\Eloq...uent\Relations\Relation and Illuminate\Database\Eloquent\Relations\Relation; however, parameter $text of Translation\Services\Tra...stOrCreateTranslation() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

184
                /** @scrutinizer ignore-type */ $defaultTranslation->translation,
Loading history...
185
                $defaultTranslation
186
            );
187
188
            return $this->makeReplacements($translation->translation, $replacements);
189
        } catch (\Illuminate\Database\QueryException $e) {
190
            // If foreign key integrity constrains fail, we have a caching issue
191
            if ($runOnce || !is_object($toLocale)) {
192
                return $text;
193
            }
194
195
            $this->removeCacheLocale($toLocale->code);
196
197
            // Burst translation cache
198
            $this->removeCacheTranslation(
199
                $this->translationModel->firstOrNew(
200
                    [
201
                    $toLocale->getForeignKey() => $toLocale->getKey(),
202
                    'translation'              => $text,
203
                    ]
204
                )
205
            );
206
207
            // Attempt translation 1 more time
208
            return $this->translate($text, $replacements, $toLocale->code, $runOnce = true);
209
        }
210
    }
211
212
    /**
213
     * {@inheritdoc}
214
     */
215
    public function getAppLocale()
216
    {
217
        return $this->config->get('app.locale');
218
    }
219
220
    /**
221
     * {@inheritdoc}
222
     */
223
    public function getRoutePrefix()
224
    {
225
        $locale = $this->request->segment($this->getConfigRequestSegment());
226
227
        $locales = $this->getConfigLocales();
228
229
        if (is_array($locales) && in_array($locale, array_keys($locales))) {
230
            return $locale;
231
        }
232
    }
233
234
    /**
235
     * {@inheritdoc}
236
     */
237
    public function getLocale()
238
    {
239
        try {
240
            return app()->getLocale();
0 ignored issues
show
The function app was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

240
            return /** @scrutinizer ignore-call */ app()->getLocale();
Loading history...
241
        } catch (Exception $e) {
242
            if($this->request->request->has('locale')) {
243
                return strtolower($this->request->input('locale'));
244
            }
245
            if ($this->request->hasHeader('locale')) {
246
                return  strtolower($this->request->header('locale'));
247
            } 
248
            if ($this->request->hasCookie('locale')) {
249
                return $this->request->cookie('locale');
250
            } 
251
            if ($this->request->hasSession() and $this->request->session()->has('locale')) {
252
                return $this->request->session()->get('locale');
253
            }
254
            if ($locale = substr($this->request->server('HTTP_ACCEPT_LANGUAGE'), 0, 2) and in_array($locale, \Illuminate\Support\Facades\Config::get('translation.locales'))) {
255
                return $locale;
256
            }
257
            return $this->getConfigDefaultLocale();
258
        }
259
    }
260
261
    public function setLanguage($locale)
262
    {
263
        $repository = app(LangResourcesRepository::class);
0 ignored issues
show
The function app was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

263
        $repository = /** @scrutinizer ignore-call */ app(LangResourcesRepository::class);
Loading history...
264
        if (!$repository->hasLangExist($locale)) {
265
            dd('Lang Dont Exist Translation');
0 ignored issues
show
The function dd was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

265
            /** @scrutinizer ignore-call */ 
266
            dd('Lang Dont Exist Translation');
Loading history...
266
        }
267
268
        Cache::set('language', $locale);
269
        $this->request->cookies->set('locale', $locale);
270
        $this->request->session()->put('locale', $locale);
271
        // CacheService::get('language', $locale);
272
        if ($user = Auth::user()) {
273
            $user->language_code = $locale;
0 ignored issues
show
Accessing language_code on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
274
            $user->save();
0 ignored issues
show
The method save() does not exist on Illuminate\Contracts\Auth\Authenticatable. ( Ignorable by Annotation )

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

274
            $user->/** @scrutinizer ignore-call */ 
275
                   save();

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...
275
        }
276
277
        return true;
278
    }
279
280
    public function getActualLanguage()
281
    {
282
        return $this->getActualLanguageCode();
283
    }
284
285
    private function getActualLanguageCode()
286
    {
287
        return config('app.locale');
0 ignored issues
show
The call to config() has too few arguments starting with defaultValue. ( Ignorable by Annotation )

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

287
        return /** @scrutinizer ignore-call */ config('app.locale');

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
288
    }
289
290
    public function getAllLanguages()
291
    {
292
        return Language::all();
293
    }
294
295
    /**
296
     * {@inheritdoc}
297
     */
298
    public function setLocale($code = '')
299
    {
300
        $this->locale = $code;
301
    }
302
303
    /**
304
     * {@inheritdoc}
305
     */
306
    public function getDefaultTranslation($text)
307
    {
308
        $locale = $this->firstOrCreateLocale($this->getConfigDefaultLocale());
309
310
        return $this->firstOrCreateTranslation($locale, $text);
311
    }
312
313
    /**
314
     * Replaces laravel translation placeholders with google
315
     * translate safe placeholders. Ex:.
316
     *
317
     * Converts:
318
     *      :name
319
     *
320
     * Into:
321
     *      __name__
322
     *
323
     * @param string $text
324
     * @param array  $replace
325
     *
326
     * @return mixed
327
     */
328
    protected function makeTranslationSafePlaceholders($text, array $replace = [])
329
    {
330
        if (count($replace) > 0) {
331
            foreach ($replace as $key => $value) {
332
                // Search for :key
333
                $search = ':'.$key;
334
335
                // Replace it with __key__
336
                $replace = $this->makeTranslationSafePlaceholder($key);
337
338
                // Perform the replacements
339
                $text = str_replace($search, $replace, $text);
340
            }
341
        }
342
343
        return $text;
344
    }
345
346
    /**
347
     * Makes a placeholder by the specified key.
348
     *
349
     * @param string $key
350
     *
351
     * @return string
352
     */
353
    protected function makeTranslationSafePlaceholder($key = '')
354
    {
355
        return '___'.strtolower($key).'___';
356
    }
357
358
    /**
359
     * Make the place-holder replacements on the specified text.
360
     *
361
     * @param string $text
362
     * @param array  $replacements
363
     *
364
     * @return string
365
     */
366
    protected function makeReplacements($text, array $replacements)
367
    {
368
        if (count($replacements) > 0) {
369
            foreach ($replacements as $key => $value) {
370
                $replace = $this->makeTranslationSafePlaceholder($key);
371
372
                $text = str_ireplace($replace, $value, $text);
373
            }
374
        }
375
376
        return $text;
377
    }
378
379
    /**
380
     * Retrieves or creates a locale from the specified code.
381
     *
382
     * @param string $code
383
     *
384
     * @return Model
385
     */
386
    protected function firstOrCreateLocale($code)
387
    {
388
        $cachedLocale = $this->getCacheLocale($code);
389
390
        if ($cachedLocale) {
391
            return $cachedLocale;
392
        }
393
394
        $name = $this->getConfigLocaleByCode($code);
395
396
        $locale = $this->localeModel->firstOrCreate(
397
            [
398
            'code' => $code,
399
            'name' => $name,
400
            ]
401
        );
402
403
        $this->setCacheLocale($locale);
404
405
        return $locale;
406
    }
407
408
    /**
409
     * Creates a translation.
410
     *
411
     * @param Model  $locale
412
     * @param string $text
413
     * @param Model  $parentTranslation
414
     *
415
     * @return Model
416
     */
417
    protected function firstOrCreateTranslation(Model $locale, $text, $parentTranslation = null)
418
    {
419
        // We'll check to see if there's a cached translation
420
        // first before we try and hit the database.
421
        $cachedTranslation = $this->getCacheTranslation($locale, $text);
422
423
        if ($cachedTranslation instanceof Model) {
424
            return $cachedTranslation;
425
        }
426
427
        // Check if auto translation is enabled. If so we'll run
428
        // the text through google translate and
429
        // save it, then cache it.
430
        if ($parentTranslation && $this->autoTranslateEnabled()) {
431
            $this->client->setSource($parentTranslation->locale->code);
0 ignored issues
show
It seems like $parentTranslation->locale->code can also be of type DateTimeZone and Illuminate\Support\HigherOrderCollectionProxy; however, parameter $source of Translation\Contracts\Client::setSource() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

431
            $this->client->setSource(/** @scrutinizer ignore-type */ $parentTranslation->locale->code);
Loading history...
The property code does not seem to exist on Illuminate\Database\Eloquent\Relations\Relation.
Loading history...
432
            $this->client->setTarget($locale->code);
0 ignored issues
show
It seems like $locale->code can also be of type Illuminate\Database\Eloq...uent\Relations\Relation and Illuminate\Database\Eloquent\Relations\Relation; however, parameter $target of Translation\Contracts\Client::setTarget() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

432
            $this->client->setTarget(/** @scrutinizer ignore-type */ $locale->code);
Loading history...
433
434
            try {
435
                $text = $this->client->translate($text);
436
            } catch (ErrorException $e) {
437
                // Request to translate failed, set the text
438
                // to the parent translation.
439
                $text = $parentTranslation->translation;
440
            } catch (UnexpectedValueException $e) {
441
                // Looks like something other than text was passed in,
442
                // we'll set the text to the parent translation
443
                // for this exception as well.
444
                $text = $parentTranslation->translation;
445
            }
446
        }
447
448
        if ($parentTranslation) {
449
            // If a parent translation is given we're looking for it's child translation.
450
            $translation = $this->translationModel->firstOrNew(
451
                [
452
                $locale->getForeignKey()                 => $locale->getKey(),
453
                $this->translationModel->getForeignKey() => $parentTranslation->getKey(),
454
                ]
455
            );
456
        } else {
457
            // Otherwise we're creating the parent translation.
458
            $translation = $this->translationModel->firstOrNew(
459
                [
460
                $locale->getForeignKey() => $locale->getKey(),
461
                'translation'            => $text,
462
                ]
463
            );
464
        }
465
466
        if (empty($translation->getAttribute('translation'))) {
467
            // We need to make sure we don't overwrite the translation
468
            // if it exists already in case it was modified.
469
            $translation->setAttribute('translation', $text);
470
        }
471
472
        if ($translation->isDirty()) {
473
            $translation->save();
474
        }
475
476
        // Cache the translation so it's retrieved faster next time
477
        $this->setCacheTranslation($translation);
478
479
        return $translation;
480
    }
481
482
    /**
483
     * Sets a cache key to the specified locale and text.
484
     *
485
     * @param Model $translation
486
     */
487
    protected function setCacheTranslation(Model $translation)
488
    {
489
        if ($translation->parent instanceof Model) {
490
            $id = $this->getTranslationCacheId($translation->locale, $translation->parent->translation);
491
        } else {
492
            $id = $this->getTranslationCacheId($translation->locale, $translation->translation);
493
        }
494
495
        if (!$this->cache->has($id)) {
496
            $this->cache->put($id, $translation, $this->cacheTime);
497
        }
498
    }
499
500
    /**
501
     * Remove the translation from the cache manually.
502
     *
503
     * @param Model $translation
504
     */
505
    public function removeCacheTranslation(Model $translation)
506
    {
507
        $id = $this->getTranslationCacheId($translation->locale, $translation->translation);
508
509
        if ($this->cache->has($id)) {
510
            $this->cache->forget($id);
511
        }
512
    }
513
514
    /**
515
     * Retrieves the cached translation from the specified locale
516
     * and text.
517
     *
518
     * @param Model  $locale
519
     * @param string $text
520
     *
521
     * @return bool|Model
522
     */
523
    protected function getCacheTranslation(Model $locale, $text)
524
    {
525
        $id = $this->getTranslationCacheId($locale, $text);
526
527
        $cachedTranslation = $this->cache->get($id);
528
529
        if ($cachedTranslation instanceof Model) {
530
            return $cachedTranslation;
531
        }
532
533
        // Cached translation wasn't found, let's return
534
        // false so we know to generate one.
535
        return false;
536
    }
537
538
    /**
539
     * Sets a cache key to the specified locale.
540
     *
541
     * @param Model $locale
542
     */
543
    protected function setCacheLocale(Model $locale)
544
    {
545
        if (!$this->cache->has($locale->code)) {
546
            $id = sprintf('translation.%s', $locale->code);
0 ignored issues
show
It seems like $locale->code can also be of type Illuminate\Database\Eloq...uent\Relations\Relation and Illuminate\Database\Eloquent\Relations\Relation; however, parameter $values of sprintf() does only seem to accept double|integer|string, maybe add an additional type check? ( Ignorable by Annotation )

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

546
            $id = sprintf('translation.%s', /** @scrutinizer ignore-type */ $locale->code);
Loading history...
547
548
            $this->cache->put($id, $locale, $this->cacheTime);
549
        }
550
    }
551
552
    /**
553
     * Retrieves a cached locale from the specified locale code.
554
     *
555
     * @param string $code
556
     *
557
     * @return bool
558
     */
559
    protected function getCacheLocale($code)
560
    {
561
        $id = sprintf('translation.%s', $code);
562
563
        if ($this->cache->has($id)) {
564
            return $this->cache->get($id);
565
        }
566
567
        return false;
568
    }
569
570
    /**
571
     * Remove a locale from the cache.
572
     *
573
     * @param string $code
574
     */
575
    protected function removeCacheLocale($code)
576
    {
577
        $id = sprintf('translation.%s', $code);
578
579
        if ($this->cache->has($id)) {
580
            $this->cache->forget($id);
581
        }
582
    }
583
584
    /**
585
     * Returns a unique translation code by compressing the text
586
     * using a PHP compression function.
587
     *
588
     * @param Model  $locale
589
     * @param string $text
590
     *
591
     * @return string
592
     */
593
    protected function getTranslationCacheId(Model $locale, $text)
594
    {
595
        $compressed = $this->compressString($text);
596
597
        return sprintf('translation.%s.%s', $locale->code, $compressed);
0 ignored issues
show
It seems like $locale->code can also be of type Illuminate\Database\Eloq...uent\Relations\Relation and Illuminate\Database\Eloquent\Relations\Relation; however, parameter $values of sprintf() does only seem to accept double|integer|string, maybe add an additional type check? ( Ignorable by Annotation )

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

597
        return sprintf('translation.%s.%s', /** @scrutinizer ignore-type */ $locale->code, $compressed);
Loading history...
598
    }
599
600
    /**
601
     * Returns a the english name of the locale code entered from the config file.
602
     *
603
     * @param string $code
604
     *
605
     * @return string
606
     */
607
    protected function getConfigLocaleByCode($code)
608
    {
609
        $locales = $this->getConfigLocales();
610
611
        if (is_array($locales) && array_key_exists($code, $locales)) {
612
            return $locales[$code];
613
        }
614
615
        return $code;
616
    }
617
618
    /**
619
     * Sets the time to store the translations and locales in cache.
620
     *
621
     * @param int $time
622
     */
623
    protected function setCacheTime($time)
624
    {
625
        if (is_numeric($time)) {
0 ignored issues
show
The condition is_numeric($time) is always true.
Loading history...
626
            $this->cacheTime = $time;
627
        }
628
    }
629
630
    /**
631
     * Returns the default locale from the configuration.
632
     *
633
     * @return string
634
     */
635
    protected function getConfigDefaultLocale()
636
    {
637
        return $this->config->get('translation.default_locale', 'en');
638
    }
639
640
    /**
641
     * Returns the locale model from the configuration.
642
     *
643
     * @return string
644
     */
645
    protected function getConfigLocaleModel()
646
    {
647
        return $this->config->get('translation.models.locale', Models\Locale::class);
0 ignored issues
show
The type Translation\Services\Models\Locale was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
648
    }
649
650
    /**
651
     * Returns the translation model from the configuration.
652
     *
653
     * @return string
654
     */
655
    protected function getConfigTranslationModel()
656
    {
657
        return $this->config->get('translation.models.translation', Models\Translation::class);
0 ignored issues
show
The type Translation\Services\Models\Translation was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
658
    }
659
660
    /**
661
     * Returns the translation client from the configuration.
662
     *
663
     * @return string
664
     */
665
    protected function getConfigClient()
666
    {
667
        return $this->config->get('translation.clients.client', Clients\GoogleTranslate::class);
0 ignored issues
show
The type Translation\Services\Clients\GoogleTranslate was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
668
    }
669
670
    /**
671
     * Returns the request segment to retrieve the locale from.
672
     *
673
     * @return int
674
     */
675
    protected function getConfigRequestSegment()
676
    {
677
        return $this->config->get('translation.request_segment', 1);
678
    }
679
680
    /**
681
     * Returns the array of configuration locales.
682
     *
683
     * @return array
684
     */
685
    protected function getConfigLocales()
686
    {
687
        return $this->config->get('translation.locales');
688
    }
689
690
    /**
691
     * Returns the cache time set from the configuration file.
692
     *
693
     * @return string|int
694
     */
695
    protected function getConfigCacheTime()
696
    {
697
        return $this->config->get('translation.cache_time', $this->cacheTime);
698
    }
699
700
    /**
701
     * Returns the auto translate configuration option.
702
     *
703
     * @return bool
704
     */
705
    protected function autoTranslateEnabled()
706
    {
707
        return $this->config->get('translation.auto_translate', true);
708
    }
709
710
    /**
711
     * Calculates the md5 hash of a string.
712
     *
713
     * Used for storing cache keys for translations.
714
     *
715
     * @param $string
716
     *
717
     * @return string
718
     */
719
    protected function compressString(string $string)
720
    {
721
        return md5($string);
722
    }
723
724
    /**
725
     * Validates the inserted text to make sure it's a string.
726
     *
727
     * @param $text
728
     *
729
     * @throws InvalidArgumentException
730
     *
731
     * @return bool
732
     */
733
    protected function validateText(string $text)
734
    {
735
        if (!is_string($text)) {
0 ignored issues
show
The condition is_string($text) is always true.
Loading history...
736
            $message = 'Invalid Argument. You must supply a string to be translated.';
737
738
            throw new InvalidArgumentException($message);
739
        }
740
741
        return true;
742
    }
743
744
    /**
745
     * Detects the Default Locale Based on
746
     */
747
748
    public function detectLocale($request)
749
    {
750
        if (!$request->hasCookie('locale')) {
751
            $locale = substr($request->server('HTTP_ACCEPT_LANGUAGE'), 0, 2);
752
753
            if (in_array($locale, \Illuminate\Support\Facades\Config::get('translation.locales'))) {
754
                $request->cookies->set('locale', $locale);
755
            }
756
        } else {
757
            $locale = $request->cookie('locale');
758
        }
759
760
        $this->setLocale($locale);
761
762
        return $locale;
763
    }
764
765
766
767
    /**
768
     * Eu trouxe de Fora @todo
769
     */
770
    public function getMenuLanguage()
771
    {
772
        $actual = $this->getActualLanguage();
773
        $languages = $this->getAllLanguages();
774
        if (empty($languages) || count($languages)<=1) {
775
            return '';
776
        }
777
778
        $activeHtml = config('app.locale');
0 ignored issues
show
The call to config() has too few arguments starting with defaultValue. ( Ignorable by Annotation )

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

778
        $activeHtml = /** @scrutinizer ignore-call */ config('app.locale');

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
779
780
        $html = '<div class="dropdown-menu dropdown-menu-right" aria-labelledby="languages">';
781
        foreach ($languages as $language) {
782
            $active = '';
783
            if ($language->code == $actual) {
784
                $active = ' active';
785
                $activeHtml = $language->code;
786
            }
787
            $html .= '<a class="dropdown-item'.$active.'" href="'.route('language.set', ['language' => $language->code]).'">'.$language->name.'</a>';
0 ignored issues
show
The function route was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

787
            $html .= '<a class="dropdown-item'.$active.'" href="'./** @scrutinizer ignore-call */ route('language.set', ['language' => $language->code]).'">'.$language->name.'</a>';
Loading history...
788
        }
789
        $html .= '</div>';
790
791
        return '<li class="nav-item dropdown">'.
792
            '<a class="nav-item nav-link dropdown-toggle mr-md-2" href="#" id="languages" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">'.
793
                $activeHtml.
794
            '</a>'.$html.'</li>';
795
    }
796
797
    public function getCurrent()
798
    {
799
        return LangRepository::getCurrent();
800
    }
801
    public function getOptionsLocales()
802
    {
803
        return LangRepository::get();
804
    }
805
806
    /**
807
     * From FAcilitador LangServiceTrait
808
     */
809
810
811
    /**
812
     * Return menu for translation
813
     *
814
     * @return string
815
     */
816
    public function menu_lang()
817
    {
818
        $langs = $this->getOptionsLocales();
819
820
        if (!$langs || empty($langs)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $langs of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
821
            return '';
822
        }
823
824
        $current = $this->getCurrent();
825
826
        $response = '<li>';
827
        $response .= '<a href=""><span class="'.$current['class'].'"></span></a>';
828
        $response .= '<ul class="sub-menu clearfix">';
829
        $response .= '<li class=\'no-translation menu-item current-lang \'><a href="'.url('language/set/'.$current['locale']).'"><span class="'.$current['class'].'"></span></a></li>';
0 ignored issues
show
The function url was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

829
        $response .= '<li class=\'no-translation menu-item current-lang \'><a href="'./** @scrutinizer ignore-call */ url('language/set/'.$current['locale']).'"><span class="'.$current['class'].'"></span></a></li>';
Loading history...
830
831
        foreach ($langs as $lang) {
832
            if ($lang['locale'] !== $current['locale']) {
833
                $response .= '<li class=\'no-translation menu-item\'><a href="'.url('language/set/'.$lang['locale']).'"><span class="'.$lang['class'].'"></span></a></li>';
834
            }
835
        }
836
837
        $response .= '</ul></li>';
838
839
        return $response;
840
    }
841
842
    /**
843
     * Build Menu para o componente de menu do  Laravel Support
844
     *
845
     * @return void
846
     */
847
    public function menuAdminLte()
848
    {
849
        $langs = $this->getOptionsLocales();
850
851
        if (!$langs || empty($langs)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $langs of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
852
            return '';
853
        }
854
855
        $current = $this->getCurrent();
856
        
857
        $response = '';
858
        $response .= '<li class="nav-item dropdown">
859
            <a class="nav-link" data-toggle="dropdown" href="#" aria-expanded="false">
860
              <i class="'.$current['class'].'"></i>
861
            </a>
862
            <div class="dropdown-menu dropdown-menu-right p-0">
863
              <a href="#" class="dropdown-item active">
864
                <i class="'.$current['class'].' mr-2"></i> '.$current['locale'].'
865
              </a>';
866
867
              // @todo
868
              // '.route('translation.language.change', [$lang['locale']]).'
869
        foreach ($langs as $lang) {
870
            if ($lang['locale'] !== $current['locale']) {
871
                $response .= '<a href="'.url('language/set/'.$lang['locale']).'" class="dropdown-item">
0 ignored issues
show
The function url was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

871
                $response .= '<a href="'./** @scrutinizer ignore-call */ url('language/set/'.$lang['locale']).'" class="dropdown-item">
Loading history...
872
                        <i class="'.$lang['class'].' mr-2"></i> '.$lang['locale'].'
873
                    </a>';
874
            }
875
        }
876
              
877
            $response .= '</div>
878
          </li>';
879
          return $response;
880
    }
881
882
    /**
883
     * Build Menu para o componente de menu do  Laravel Support
884
     *
885
     * @return void
886
     */
887
    public function menuBuilder()
888
    {
889
890
        $langs = LangRepository::get();
891
892
        if (!$langs || empty($langs)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $langs of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
893
            return [];
894
        }
895
        $current = LangRepository::getCurrent();
896
897
        $array = [
898
            [
899
                'text'        => $current['locale'],
900
                'url'       => url('sitec/language/set/'.$current['locale']),
0 ignored issues
show
The function url was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

900
                'url'       => /** @scrutinizer ignore-call */ url('sitec/language/set/'.$current['locale']),
Loading history...
901
                'icon'        => $current['class'],
902
                // 'topnav' => true,
903
                // 'topnav_user' => true,
904
                'topnav_right' => true,
905
                // 'access' => \Porteiro\Models\Role::$ADMIN
906
            ],
907
            $current['locale'] => [
908
909
            ],
910
        ];
911
912
        foreach ($langs as $lang) {
913
914
            if ($lang['locale'] !== $current['locale']) {
915
                $array[$current['locale']][] = [
916
                    'text'        => $lang['locale'],
917
                    'url'       => url('sitec/language/set/'.$lang['locale']),
918
                    'icon'        => $lang['class'],
919
                    'topnav_right' => true,
920
                    // 'level'       => 3, // 0 (Public), 1, 2 (Admin) , 3 (Root)
921
                ];
922
            }
923
        }
924
925
        return $array;
926
927
    }
928
929
    /**
930
     * Get a especific image for current Lang.
931
     *
932
     * @param string $img_path
933
     *
934
     * @return string
935
     */
936
    public function img_lang($img_path)
937
    {
938
        $public_path = public_path();
0 ignored issues
show
The function public_path was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

938
        $public_path = /** @scrutinizer ignore-call */ public_path();
Loading history...
939
940
        $current = LangRepository::getCurrent();
941
        $min_lang = explode('-', $current['locale']);
942
943
        $break_path = explode('.', $img_path);
944
945
        $extensao = array_pop($break_path);
946
947
        if (file_exists($public_path.'/'.implode('.', $break_path).'-'.$current['locale'].'.'.$extensao)) {
948
            return implode('.', $break_path).'-'.$current['locale'].'.'.$extensao;
949
        }
950
951
        if (file_exists($public_path.'/'.implode('.', $break_path).'-'.$min_lang[0].'.'.$extensao)) {
952
            return implode('.', $break_path).'-'.$min_lang[0].'.'.$extensao;
953
        }
954
955
        return $img_path;
956
    }
957
}
958