Completed
Push — master ( 1b7c9c...cf42d1 )
by Avtandil
03:25
created

MultiLang::getRedirectUrl()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 5.0214

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 29
ccs 19
cts 21
cp 0.9048
rs 8.439
cc 5
eloc 19
nc 5
nop 1
crap 5.0214
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 Illuminate\Contracts\Cache\Factory as CacheContract;
14
use Illuminate\Database\DatabaseManager as DatabaseContract;
15
use Illuminate\Support\Collection;
16
use Illuminate\Http\Request;
17
use InvalidArgumentException;
18
19
class MultiLang
20
{
21
    /**
22
     * Language/Locale.
23
     *
24
     * @var string
25
     */
26
    protected $lang;
27
28
    /**
29
     * Default Language/Locale.
30
     *
31
     * @var string
32
     */
33
    protected $default_lang;
34
35
    /**
36
     * System environment
37
     *
38
     * @var string
39
     */
40
    protected $environment;
41
42
    /**
43
     * The instance of the cache.
44
     *
45
     * @var \Illuminate\Cache\CacheManager
46
     */
47
    protected $cache;
48
49
    /**
50
     * Config.
51
     *
52
     * @var array
53
     */
54
    protected $config;
55
56
    /**
57
     * The instance of the database.
58
     *
59
     * @var \Illuminate\Database\DatabaseManager
60
     */
61
    protected $db;
62
63
    /**
64
     * Name of the cache.
65
     *
66
     * @var string
67
     */
68
    protected $cache_name;
69
70
    /**
71
     * Texts collection.
72
     *
73
     * @var \Illuminate\Support\Collection
74
     */
75
    protected $texts;
76
77
    /**
78
     * Missing texts.
79
     *
80
     * @var array
81
     */
82
    protected $new_texts;
83
84
    /**
85
     * Create a new MultiLang instance.
86
     *
87
     * @param  string                               $environment
88
     * @param  array                                $config
89
     * @param  \Illuminate\Cache\CacheManager       $cache
90
     * @param  \Illuminate\Database\DatabaseManager $db
91
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
92
     */
93 23
    public function __construct($environment, array $config, CacheContract $cache, DatabaseContract $db)
94
    {
95 23
        $this->environment = $environment;
96 23
        $this->cache       = $cache;
0 ignored issues
show
Documentation Bug introduced by
$cache is of type object<Illuminate\Contracts\Cache\Factory>, but the property $cache was declared to be of type object<Illuminate\Cache\CacheManager>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
97 23
        $this->db          = $db;
98
99 23
        $this->setConfig($config);
100 23
    }
101
102 23
    public function setConfig(array $config)
103
    {
104 23
        $this->config = $this->getDefaultConfig();
105
106 23
        foreach ($config as $k => $v) {
107 3
            $this->config[$k] = $v;
108 23
        }
109 23
    }
110
111 23
    public function getDefaultConfig()
112
    {
113
        $config = [
114 23
            'enabled'        => true,
115
            'locales'        => [
116
                'en' => [
117 23
                    'name'        => 'English',
118 23
                    'native_name' => 'English',
119 23
                    'default'     => true,
120 23
                ],
121 23
            ],
122 23
            'autosave'       => true,
123 23
            'cache'          => true,
124 23
            'cache_lifetime' => 1440,
125 23
            'texts_table'    => 'texts',
126 23
        ];
127 23
        return $config;
128
    }
129
130 21
    public function getConfig($key = null)
131
    {
132 21
        if ($key === null) {
133 1
            return $this->config;
134
        }
135
136 21
        return isset($this->config[$key]) ? $this->config[$key] : null;
137
    }
138
139
    /**
140
     * Set locale and load texts
141
     *
142
     * @param  string $lang
143
     * @param  string $default_lang
144
     * @param  array  $text
0 ignored issues
show
Bug introduced by
There is no parameter named $text. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
145
     * @return void
146
     */
147 22
    public function setLocale($lang, $default_lang = null, $texts = null)
148
    {
149 22
        if (!$lang) {
150 1
            throw new InvalidArgumentException('Locale is empty');
151
        }
152 21
        $this->lang = $lang;
153
154 21
        if ($default_lang === null) {
155 20
            $default_lang = $lang;
156 20
        }
157
158 21
        $this->default_lang = $default_lang;
159
160 21
        $this->setCacheName($lang);
161
162 21
        if (is_array($texts)) {
163 1
            $texts = new Collection($texts);
164 1
        }
165
166 21
        if ($texts === null) {
167 20
            $texts = $this->loadTexts($this->getLocale());
168 20
        }
169
170 21
        $this->texts = new Collection($texts);
171 21
    }
172
173
    /**
174
     * Load texts
175
     *
176
     * @param  string  $lang
177
     * @return array
178
     */
179 20
    public function loadTexts($lang = null)
180
    {
181 20
        $cache = $this->getConfig('cache');
182
183 20
        if (!$cache || $this->cache === null || $this->environment != 'production') {
184 17
            $texts = $this->loadTextsFromDatabase($lang);
185 17
            return $texts;
186
        }
187
188 4
        if ($this->mustLoadFromCache()) {
189
            $texts = $this->loadTextsFromCache();
190
        } else {
191 4
            $texts = $this->loadTextsFromDatabase($lang);
192 4
            $this->storeTextsInCache($texts);
193
        }
194
195 4
        return $texts;
196
    }
197
198
    /**
199
     * Get translated text
200
     *
201
     * @param  string   $key
202
     * @param  string   $default
0 ignored issues
show
Bug introduced by
There is no parameter named $default. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
203
     * @return string
204
     */
205 7
    public function get($key)
206
    {
207
208 7
        if (empty($key)) {
209 1
            throw new InvalidArgumentException('String key not provided');
210
        }
211
212 6
        if (!$this->lang) {
213 1
            return $key;
214
        }
215
216 5
        if (!$this->texts->has($key)) {
217 4
            $this->queueToSave($key);
218 4
            return $key;
219
        }
220
221 1
        $text = $this->texts->get($key);
222
223 1
        return $text;
224
    }
225
226
    /**
227
     * Get texts
228
     *
229
     * @return array
230
     */
231 4
    public function getRedirectUrl(Request $request)
232
    {
233 4
        $locale          = $request->segment(1);
234 4
        $fallback_locale = $this->default_lang;
235
236 4
        if (strlen($locale) == 2) {
237 3
            $locales = $this->getConfig('locales');
238
239 3
            if (!isset($locales[$locale])) {
240 2
                $segments    = $request->segments();
241 2
                $segments[0] = $fallback_locale;
242 2
                $url         = implode('/', $segments);
243 2
                if ($query_string = $request->server->get('QUERY_STRING')) {
244 1
                    $url .= '?' . $query_string;
245 1
                }
246
247 2
                return $url;
248
            }
249 1
        } else {
250 1
            $segments = $request->segments();
251 1
            $url      = $fallback_locale . '/' . implode('/', $segments);
252 1
            if ($query_string = $request->server->get('QUERY_STRING')) {
253
                $url .= '?' . $query_string;
254
            }
255 1
            return $url;
256
        }
257
258 1
        return null;
259
    }
260
261
262
263
    /**
264
     * Get texts
265
     *
266
     * @return array
267
     */
268 4
    public function getTexts()
269
    {
270
271 4
        return $this->texts->toArray();
272
    }
273
274
    /**
275
     * Set texts manually
276
     *
277
     * @param  array                                 $texts_array
278
     * @return \Longman\LaravelMultiLang\MultiLang
279
     */
280 3
    public function setTexts(array $texts_array)
281
    {
282 3
        $texts = [];
283 3
        foreach ($texts_array as $key => $value) {
284 3
            $texts[$key] = $value;
285 3
        }
286
287 3
        $this->texts = new Collection($texts);
288
289 3
        return $this;
290
    }
291
292
    /**
293
     * Queue missing texts
294
     *
295
     * @param  string $key
296
     * @return void
297
     */
298 4
    protected function queueToSave($key)
299
    {
300 4
        $this->new_texts[$key] = $key;
301 4
    }
302
303
    /**
304
     * Check if we must load texts from cache
305
     *
306
     * @return bool
307
     */
308 4
    public function mustLoadFromCache()
309
    {
310 4
        return $this->cache->has($this->getCacheName());
311
    }
312
313 4
    protected function storeTextsInCache(array $texts)
314
    {
315 4
        $cache_lifetime = $this->getConfig('cache_lifetime', 1440);
0 ignored issues
show
Unused Code introduced by
The call to MultiLang::getConfig() has too many arguments starting with 1440.

This check compares calls to functions or methods with their respective definitions. If the call has more 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.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
316 4
        $status         = $this->cache->put($this->getCacheName(), $texts, $cache_lifetime);
317 4
        return $status;
318
    }
319
320 20
    public function loadTextsFromDatabase($lang)
321
    {
322 20
        $texts = $lang ? $this->db->table($this->getTableName())
323 20
            ->where('lang', $lang)
324 20
            ->get(['key', 'value', 'lang', 'scope']) : $this->db->table($this->getTableName())->get(['key', 'value', 'lang', 'scope']);
325
326 20
        $array = [];
327 20
        foreach ($texts as $row) {
328 14
            $array[$row->key] = $row->value;
329 20
        }
330 20
        return $array;
331
    }
332
333 1
    public function loadTextsFromCache()
334
    {
335 1
        $texts = $this->cache->get($this->getCacheName());
0 ignored issues
show
Bug introduced by
The method get() cannot be called from this context as it is declared protected in class Illuminate\Cache\CacheManager.

This check looks for access to methods that are not accessible from the current context.

If you need to make a method accessible to another context you can raise its visibility level in the defining class.

Loading history...
336
337 1
        return $texts;
338
    }
339
340 21
    public function setCacheName($lang)
341
    {
342 21
        $this->cache_name = $this->getConfig('texts_table') . '_' . $lang;
343 21
    }
344
345 4
    public function getCacheName()
346
    {
347 4
        return $this->cache_name;
348
    }
349
350 1
    public function getUrl($path)
351
    {
352 1
        $locale = $this->getLocale();
353 1
        if ($locale) {
354 1
            $path = $locale . '/' . $path;
355 1
        }
356 1
        return $path;
357
    }
358
359 2
    public function autoSaveIsAllowed()
360
    {
361 2
        if ($this->environment == 'local' && $this->getConfig('autosave') && $this->db !== null) {
362 1
            return true;
363
        }
364 2
        return false;
365
    }
366
367 20
    public function getLocale()
368
    {
369 20
        return $this->lang;
370
    }
371
372 3
    public function saveTexts()
373
    {
374 3
        if (empty($this->new_texts)) {
375 3
            return false;
376
        }
377
378 3
        $table = $this->getTableName();
379 3
        $locales = $this->getConfig('locales');
380 3
        foreach ($this->new_texts as $k => $v) {
381 3
            foreach($locales as $lang => $locale_data) {
382 3
                $exists = $this->db->table($table)->where([
383 3
                    'key'  => $k,
384 3
                    'lang' => $lang,
385 3
                ])->first();
386
387 3
                if ($exists) {
388 1
                    continue;
389
                }
390
391 3
                $this->db->table($table)->insert([
392 3
                    'key'   => $k,
393 3
                    'lang'  => $lang,
394 3
                    'value' => $v,
395 3
                ]);
396
397 3
            }
398
399 3
        }
400 3
        return true;
401
    }
402
403 20
    protected function getTableName()
404
    {
405 20
        $table = $this->getConfig('texts_table');
406 20
        return $table;
407
    }
408
}
409