Test Failed
Push — master ( ffdf4e...19cafa )
by Avtandil
04:06
created

MultiLang::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 4
dl 0
loc 10
ccs 0
cts 8
cp 0
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/*
3
 * This file is part of the Laravel MultiLang package.
4
 *
5
 * (c) Avtandil Kikabidze aka LONGMAN <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Longman\LaravelMultiLang;
12
13
use Closure;
14
use Illuminate\Cache\CacheManager as Cache;
15
use Illuminate\Database\DatabaseManager as Database;
16
use Illuminate\Http\Request;
17
use Illuminate\Support\Collection;
18
use Illuminate\Support\Str;
19
use InvalidArgumentException;
20
21
class MultiLang
22
{
23
    /**
24
     * Language/Locale.
25
     *
26
     * @var string
27
     */
28
    protected $lang;
29
30
    /**
31
     * System environment
32
     *
33
     * @var string
34
     */
35
    protected $environment;
36
37
    /**
38
     * Config.
39
     *
40
     * @var \Longman\LaravelMultiLang\Config
41
     */
42
    protected $config;
43
44
    /**
45
     * Repository
46
     *
47
     * @var \Longman\LaravelMultiLang\Repository
48
     */
49
    protected $repository;
50
51
    /**
52
     * Texts.
53
     *
54
     * @var array
55
     */
56
    protected $texts;
57
58
    /**
59
     * Missing texts.
60
     *
61
     * @var array
62
     */
63
    protected $new_texts;
64
65
    /**
66
     * Application scope.
67
     *
68
     * @var string
69
     */
70
    protected $scope;
71
72
    /**
73
     * Create a new MultiLang instance.
74
     *
75
     * @param string                               $environment
76
     * @param array                                $config
77
     * @param \Illuminate\Cache\CacheManager       $cache
78
     * @param \Illuminate\Database\DatabaseManager $db
79
     */
80
    public function __construct($environment, array $config, Cache $cache, Database $db)
81
    {
82
        $this->environment = $environment;
83
        $this->cache       = $cache;
0 ignored issues
show
Bug introduced by
The property cache does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
84
        $this->db          = $db;
0 ignored issues
show
Bug introduced by
The property db does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
85
86
        $this->setConfig($config);
87
88
        $this->setRepository(new Repository($this->config, $cache, $db));
89
    }
90
91
    /**
92
     * Set multilang config
93
     *
94
     * @param array $config
95
     * @return $this
96
     */
97
    public function setConfig(array $config)
98
    {
99
        $this->config = new Config($config);
100
        return $this;
101
    }
102
103
    /**
104
     * Set repository object
105
     *
106
     * @param \Longman\LaravelMultiLang\Repository $repository
107
     * @return $this
108
     */
109
    public function setRepository(Repository $repository)
110
    {
111
        $this->repository = $repository;
112
        return $this;
113
    }
114
115
    /**
116
     * Get repository object
117
     *
118
     * @return \Longman\LaravelMultiLang\Repository
119
     */
120
    public function getRepository()
121
    {
122
        return $this->repository;
123
    }
124
125
    /**
126
     * Set application scope
127
     *
128
     * @param $scope
129
     * @return $this
130
     */
131
    public function setScope($scope)
132
    {
133
        $this->scope = $scope;
134
        return $this;
135
    }
136
137
    /**
138
     * Get application scope
139
     *
140
     * @return string
141
     */
142
    public function getScope()
143
    {
144
        return $this->scope;
145
    }
146
147
    /**
148
     * Set locale and load texts
149
     *
150
     * @param  string $lang
151
     * @param  array  $texts
152
     * @return void
153
     */
154
    public function setLocale($lang, array $texts = null)
155
    {
156
        if (!$lang) {
157
            throw new InvalidArgumentException('Locale is empty');
158
        }
159
        $this->lang = $lang;
160
161
        if (!is_array($texts)) {
162
            $texts = $this->loadTexts($this->getLocale(), $this->scope);
163
        }
164
165
        $this->texts = $texts;
166
    }
167
168
    /**
169
     * Load texts
170
     *
171
     * @param  string $lang
172
     * @param  string $scope
173
     * @return array
174
     */
175
    public function loadTexts($lang, $scope = null)
176
    {
177
        if ($this->environment != 'production' || $this->config->get('cache.enabled', true) === false) {
178
            $texts = $this->repository->loadFromDatabase($lang, $scope);
179
            return $texts;
180
        }
181
182
        if ($this->repository->existsInCache($lang)) {
183
            $texts = $this->repository->loadFromCache($lang, $scope);
184
        } else {
185
            $texts = $this->repository->loadFromDatabase($lang, $scope);
186
            $this->repository->storeInCache($lang, $texts, $scope);
187
        }
188
189
        return $texts;
190
    }
191
192
    /**
193
     * Get translated text
194
     *
195
     * @param  string $key
196
     * @param  array  $replace
197
     * @return string
198
     */
199
    public function get($key, array $replace = [])
200
    {
201
202
        if (empty($key)) {
203
            throw new InvalidArgumentException('String key not provided');
204
        }
205
206
        if (!$this->lang) {
207
            return $key;
208
        }
209
210
        if (!isset($this->texts[$key])) {
211
            $this->queueToSave($key);
212
            return $this->replaceMarkers($key, $replace);
213
        }
214
215
        $text = $this->texts[$key];
216
217
        return $this->replaceMarkers($text, $replace);
218
    }
219
220
    /**
221
     * Replace markers in text
222
     *
223
     * @param  string $text
224
     * @param  array  $replace
225
     * @return string
226
     */
227
    protected function replaceMarkers($text, array $replace = [])
228
    {
229
        if (empty($replace)) {
230
            return $text;
231
        }
232
233
        return $this->makeReplacements($text, $replace);
234
    }
235
236
    /**
237
     * Make the place-holder replacements on a line.
238
     *
239
     * @param  string $text
240
     * @param  array  $replace
241
     * @return string
242
     */
243
    protected function makeReplacements($text, array $replace)
244
    {
245
        $replace = $this->sortReplacements($replace);
246
247
        foreach ($replace as $key => $value) {
248
            $text = str_replace(
249
                [':' . $key, ':' . Str::upper($key), ':' . Str::ucfirst($key)],
250
                [$value, Str::upper($value), Str::ucfirst($value)],
251
                $text
252
            );
253
        }
254
255
        return $text;
256
    }
257
258
    /**
259
     * Sort the replacements array.
260
     *
261
     * @param  array $replace
262
     * @return \Illuminate\Support\Collection
263
     */
264
    protected function sortReplacements(array $replace)
265
    {
266
        return (new Collection($replace))->sortBy(function ($value, $key) {
267
            return mb_strlen($key) * -1;
268
        });
269
    }
270
271
    /**
272
     * Get redirect url in middleware
273
     *
274
     * @param \Illuminate\Http\Request $request
275
     * @return null|string
276
     */
277
    public function getRedirectUrl(Request $request)
278
    {
279
        $locale           = $request->segment(1);
280
        $fallback_locale  = $this->config->get('default_locale', 'en');
281
        $exclude_segments = $this->config->get('exclude_segments', []);
282
        if (in_array($locale, $exclude_segments)) {
283
            return null;
284
        }
285
286
        if (strlen($locale) == 2) {
287
            $locales = $this->config->get('locales', []);
288
289
            if (!isset($locales[$locale])) {
290
                $segments    = $request->segments();
291
                $segments[0] = $fallback_locale;
292
                $url         = implode('/', $segments);
293
                if ($query_string = $request->server->get('QUERY_STRING')) {
294
                    $url .= '?' . $query_string;
295
                }
296
297
                return $url;
298
            }
299
        } else {
300
            $segments = $request->segments();
301
            $url      = $fallback_locale . '/' . implode('/', $segments);
302
            if ($query_string = $request->server->get('QUERY_STRING')) {
303
                $url .= '?' . $query_string;
304
            }
305
            return $url;
306
        }
307
308
        return null;
309
    }
310
311
    /**
312
     * Detect locale based on url segment
313
     *
314
     * @param \Illuminate\Http\Request $request
315
     * @return string
316
     */
317
    public function detectLocale(Request $request)
318
    {
319
        $locale  = $request->segment(1);
320
        $locales = $this->config->get('locales');
321
322
        if (isset($locales[$locale])) {
323
            return isset($locales[$locale]['locale']) ? $locales[$locale]['locale'] : $locale;
324
        }
325
326
        return $this->config->get('default_locale', 'en');
327
    }
328
329
    /**
330
     * Wrap routes to available languages group
331
     *
332
     * @param \Closure $callback
333
     */
334
    public function routeGroup(Closure $callback)
335
    {
336
        $router = app('router');
337
338
        $locales = $this->config->get('locales', []);
339
340
        foreach ($locales as $locale => $val) {
341
            $router->group([
342
                               'prefix' => $locale,
343
                               'as'     => $locale . '.',
344
                           ], $callback);
345
        }
346
    }
347
348
    /**
349
     *  Manage texts
350
     */
351
    public function manageTextsRoutes()
352
    {
353
        $router     = app('router');
354
        $route      = $this->config->get('text-route.route', 'texts');
355
        $controller = $this->config->get(
356
            'text-route.controller',
357
            '\Longman\LaravelMultiLang\Controllers\TextsController'
358
        );
359
360
        $router->get(
361
            $route,
362
            ['uses' => $controller . '@index']
363
        );
364
        $router->post(
365
            $route,
366
            ['uses' => $controller . '@save']
367
        );
368
    }
369
370
    /**
371
     * Get texts
372
     *
373
     * @return array
374
     */
375
    public function getTexts()
376
    {
377
378
        return $this->texts;
379
    }
380
381
    /**
382
     * Get all texts
383
     *
384
     * @param string $lang
385
     * @param string $scope
386
     * @return array
387
     */
388
    public function getAllTexts($lang = null, $scope = null)
389
    {
390
        return $this->repository->loadAllFromDatabase($lang, $scope);
391
    }
392
393
    /**
394
     * Set texts manually
395
     *
396
     * @param  array $texts_array
397
     * @return \Longman\LaravelMultiLang\MultiLang
398
     */
399
    public function setTexts(array $texts_array)
400
    {
401
        $texts = [];
402
        foreach ($texts_array as $key => $value) {
403
            $texts[$key] = $value;
404
        }
405
406
        $this->texts = $texts;
407
408
        return $this;
409
    }
410
411
    /**
412
     * Queue missing texts
413
     *
414
     * @param  string $key
415
     * @return void
416
     */
417
    protected function queueToSave($key)
418
    {
419
        $this->new_texts[$key] = $key;
420
    }
421
422
    /**
423
     * Get language prefixed url
424
     *
425
     * @param $path
426
     * @return string
427
     */
428
    public function getUrl($path)
429
    {
430
        $locale = $this->getLocale();
431
        if ($locale) {
432
            $path = $locale . '/' . $path;
433
        }
434
        return $path;
435
    }
436
437
    /**
438
     * Check if autosave allowed
439
     *
440
     * @return bool
441
     */
442
    public function autoSaveIsAllowed()
443
    {
444
        if ($this->environment == 'local' && $this->config->get('db.autosave', true)) {
445
            return true;
446
        }
447
        return false;
448
    }
449
450
    /**
451
     * Get locale
452
     *
453
     * @return string
454
     */
455
    public function getLocale()
456
    {
457
        return $this->lang;
458
    }
459
460
    /**
461
     * Get available locales
462
     *
463
     * @return array
464
     */
465
    public function getLocales()
466
    {
467
        return $this->config->get('locales');
468
    }
469
470
    /**
471
     * Save missing texts
472
     *
473
     * @return bool
474
     */
475
    public function saveTexts()
476
    {
477
        if (empty($this->new_texts)) {
478
            return false;
479
        }
480
481
        $this->repository->save($this->new_texts, $this->scope);
482
        return true;
483
    }
484
}
485