Completed
Push — master ( f34cee...bc60be )
by Avtandil
05:18
created

MultiLang::replaceMarkers()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 4
c 1
b 0
f 1
nc 2
nop 2
dl 0
loc 8
ccs 4
cts 4
cp 1
crap 2
rs 9.4285
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 InvalidArgumentException;
18
use Illuminate\Support\Str;
19
use Illuminate\Support\Collection;
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 24
    public function __construct($environment, array $config, Cache $cache, Database $db)
81
    {
82 24
        $this->environment = $environment;
83 24
        $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 24
        $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 24
        $this->setConfig($config);
87
88 24
        $this->setRepository(new Repository($this->config, $cache, $db));
89 24
    }
90
91
    /**
92
     * Set multilang config
93
     *
94
     * @param array $config
95
     * @return $this
96
     */
97 24
    public function setConfig(array $config)
98
    {
99 24
        $this->config = new Config($config);
100 24
        return $this;
101
    }
102
103
    /**
104
     * Set repository object
105
     *
106
     * @param \Longman\LaravelMultiLang\Repository $repository
107
     * @return $this
108
     */
109 24
    public function setRepository(Repository $repository)
110
    {
111 24
        $this->repository = $repository;
112 24
        return $this;
113
    }
114
115
    /**
116
     * Get repository object
117
     *
118
     * @return \Longman\LaravelMultiLang\Repository
119
     */
120 2
    public function getRepository()
121
    {
122 2
        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 22
    public function setLocale($lang, array $texts = null)
155
    {
156 22
        if (!$lang) {
157 1
            throw new InvalidArgumentException('Locale is empty');
158
        }
159 21
        $this->lang = $lang;
160
161 21
        if (!is_array($texts)) {
162 18
            $texts = $this->loadTexts($this->getLocale(), $this->scope);
163
        }
164
165 21
        $this->texts = $texts;
166 21
    }
167
168
    /**
169
     * Load texts
170
     *
171
     * @param  string $lang
172
     * @param  string $scope
173
     * @return array
174
     */
175 18
    public function loadTexts($lang, $scope = null)
176
    {
177 18
        if ($this->environment != 'production' || $this->config->get('cache.enabled', true) === false) {
178 16
            $texts = $this->repository->loadFromDatabase($lang, $scope);
179 16
            return $texts;
180
        }
181
182 3
        if ($this->repository->existsInCache($lang)) {
183
            $texts = $this->repository->loadFromCache($lang, $scope);
184
        } else {
185 3
            $texts = $this->repository->loadFromDatabase($lang, $scope);
186 3
            $this->repository->storeInCache($lang, $texts, $scope);
187
        }
188
189 3
        return $texts;
190
    }
191
192
    /**
193
     * Get translated text
194
     *
195
     * @param  string $key
196
     * @param  array  $replace
197
     * @return string
198
     */
199 9
    public function get($key, array $replace = [])
200
    {
201
202 9
        if (empty($key)) {
203 1
            throw new InvalidArgumentException('String key not provided');
204
        }
205
206 8
        if (!$this->lang) {
207 1
            return $key;
208
        }
209
210 7
        if (!isset($this->texts[$key])) {
211 4
            $this->queueToSave($key);
212 4
            return $this->replaceMarkers($key, $replace);
213
        }
214
215 3
        $text = $this->texts[$key];
216
217 3
        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 7
    protected function replaceMarkers($text, array $replace = [])
228
    {
229 7
        if (empty($replace)) {
230 6
            return $text;
231
        }
232
233 1
        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 1
    protected function makeReplacements($text, array $replace)
244
    {
245 1
        $replace = $this->sortReplacements($replace);
246
247 1
        foreach ($replace as $key => $value) {
248 1
            $text = str_replace(
249 1
                [':' . $key, ':' . Str::upper($key), ':' . Str::ucfirst($key)],
250 1
                [$value, Str::upper($value), Str::ucfirst($value)],
251
                $text
252
            );
253
        }
254
255 1
        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 1
        return (new Collection($replace))->sortBy(function ($value, $key) {
267 1
            return mb_strlen($key) * -1;
268 1
        });
269
    }
270
271
    /**
272
     * Get redirect url in middleware
273
     *
274
     * @param \Illuminate\Http\Request $request
275
     * @return null|string
276
     */
277 4
    public function getRedirectUrl(Request $request)
278
    {
279 4
        $locale           = $request->segment(1);
280 4
        $fallback_locale  = $this->config->get('default_locale', 'en');
281 4
        $exclude_segments = $this->config->get('exclude_segments', []);
282 4
        if (in_array($locale, $exclude_segments)) {
283
            return null;
284
        }
285
286 4
        if (strlen($locale) == 2) {
287 3
            $locales = $this->config->get('locales', []);
288
289 3
            if (!isset($locales[$locale])) {
290 2
                $segments    = $request->segments();
291 2
                $segments[0] = $fallback_locale;
292 2
                $url         = implode('/', $segments);
293 2
                if ($query_string = $request->server->get('QUERY_STRING')) {
294 1
                    $url .= '?' . $query_string;
295
                }
296
297 3
                return $url;
298
            }
299
        } else {
300 1
            $segments = $request->segments();
301 1
            $url      = $fallback_locale . '/' . implode('/', $segments);
302 1
            if ($query_string = $request->server->get('QUERY_STRING')) {
303
                $url .= '?' . $query_string;
304
            }
305 1
            return $url;
306
        }
307
308 1
        return null;
309
    }
310
311
    /**
312
     * Detect locale based on url segment
313
     *
314
     * @param \Illuminate\Http\Request $request
315
     * @return string
316
     */
317 1
    public function detectLocale(Request $request)
318
    {
319 1
        $locale  = $request->segment(1);
320 1
        $locales = $this->config->get('locales');
321
322 1
        if (isset($locales[$locale])) {
323 1
            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
    /**
350
     *  Manage texts
351
     */
352
    public function manageTextsRoutes()
353
    {
354
        $router     = app('router');
355
        $route      = $this->config->get('text-route.route', 'texts');
356
        $controller = $this->config->get(
357
            'text-route.controller',
358
            '\Longman\LaravelMultiLang\Controllers\TextsController'
359
        );
360
361
        $router->get(
362
            $route,
363
            ['uses' => $controller . '@index']
364
        );
365
        $router->post(
366
            $route,
367
            ['uses' => $controller . '@save']
368
        );
369
    }
370
371
    /**
372
     * Get texts
373
     *
374
     * @return array
375
     */
376 4
    public function getTexts()
377
    {
378
379 4
        return $this->texts;
380
    }
381
382
    /**
383
     * Set texts manually
384
     *
385
     * @param  array $texts_array
386
     * @return \Longman\LaravelMultiLang\MultiLang
387
     */
388 4
    public function setTexts(array $texts_array)
389
    {
390 4
        $texts = [];
391 4
        foreach ($texts_array as $key => $value) {
392 4
            $texts[$key] = $value;
393
        }
394
395 4
        $this->texts = $texts;
396
397 4
        return $this;
398
    }
399
400
    /**
401
     * Queue missing texts
402
     *
403
     * @param  string $key
404
     * @return void
405
     */
406 4
    protected function queueToSave($key)
407
    {
408 4
        $this->new_texts[$key] = $key;
409 4
    }
410
411
    /**
412
     * Get language prefixed url
413
     *
414
     * @param $path
415
     * @return string
416
     */
417 2
    public function getUrl($path)
418
    {
419 2
        $locale = $this->getLocale();
420 2
        if ($locale) {
421 2
            $path = $locale . '/' . $path;
422
        }
423 2
        return $path;
424
    }
425
426
    /**
427
     * Check if autosave allowed
428
     *
429
     * @return bool
430
     */
431 4
    public function autoSaveIsAllowed()
432
    {
433 4
        if ($this->environment == 'local' && $this->config->get('db.autosave', true)) {
434 1
            return true;
435
        }
436 4
        return false;
437
    }
438
439
    /**
440
     * Get locale
441
     *
442
     * @return string
443
     */
444 19
    public function getLocale()
445
    {
446 19
        return $this->lang;
447
    }
448
449
    /**
450
     * Get available locales
451
     *
452
     * @return array
453
     */
454 1
    public function getLocales()
455
    {
456 1
        return $this->config->get('locales');
457
    }
458
459
    /**
460
     * Save missing texts
461
     *
462
     * @return bool
463
     */
464 3
    public function saveTexts()
465
    {
466 3
        if (empty($this->new_texts)) {
467 3
            return false;
468
        }
469
470 3
        $this->repository->save($this->new_texts, $this->scope);
471 3
        return true;
472
    }
473
}
474