Completed
Push — master ( 240820...6ab7c2 )
by Maxime
02:31
created

Locale::getAcceptedLanguages()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
nc 6
nop 1
dl 0
loc 17
ccs 0
cts 14
cp 0
crap 30
rs 9.3888
c 0
b 0
f 0
1
<?php
2
3
namespace Distilleries\Contentful\Models;
4
5
use Illuminate\Http\Request;
6
use Illuminate\Support\Facades\Cache;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Support\Str;
9
10
/**
11
 * @property integer $id
12
 * @property string $label
13
 * @property string $code
14
 * @property string $fallback_code
15
 * @property boolean $is_editable
16
 * @property boolean $is_publishable
17
 * @property \Illuminate\Support\Carbon $created_at
18
 * @property \Illuminate\Support\Carbon $updated_at
19
 */
20
class Locale extends Model
21
{
22
    /**
23
     * {@inheritdoc}
24
     */
25
    protected $table = 'locales';
26
27
    /**
28
     * {@inheritdoc}
29
     */
30
    protected $fillable = [
31
        'label',
32
        'code',
33
        'locale',
34
        'country',
35
        'fallback_code',
36
        'is_default',
37
        'is_editable',
38
        'is_publishable',
39
    ];
40
41
    /**
42
     * {@inheritdoc}
43
     */
44
    protected $casts = [
45
        'is_default' => 'boolean',
46
        'is_editable' => 'boolean',
47
        'is_publishable' => 'boolean',
48
    ];
49
50
    /**
51
     * Return default locale code.
52
     *
53
     * @return string
54
     */
55 View Code Duplication
    public static function default(): string
2 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style introduced by
Possible parse error: non-abstract method defined as abstract
Loading history...
56
    {
57
        $default = Cache::get('locale_default');
1 ignored issue
show
Coding Style introduced by
The visibility should be declared for property $default.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
58
59
        if ($default === null)
1 ignored issue
show
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
Coding Style introduced by
The visibility should be declared for property $default.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
60
        {
61
            $default = static::query()
0 ignored issues
show
Bug introduced by
The method select() does not exist on Illuminate\Database\Eloquent\Builder. Did you maybe mean createSelectWithConstraint()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
62
                ->select('locale')
63
                ->where('is_default', '=', true)
64
                ->first();
65
66
            $default = !empty($default) ? $default->locale : config('contentful.default_locale');
2 ignored issues
show
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
Coding Style introduced by
The visibility should be declared for property $default.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
67
            // Cache is cleaned in Console\Commands\SyncLocales (run at least daily)
68
            Cache::forever('locale_default', $default);
1 ignored issue
show
Coding Style introduced by
The visibility should be declared for property $default.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
69
        }
70
71
        return $default;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $default.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
72
    }
73
74
75
    public static function getAppOrDefaultLocale(): string
76
    {
77
        return app()->getLocale() ?? self::default();
78
    }
79
80
    public static function getAppOrDefaultCountry($key = 'app.country'): string
81
    {
82
        return config($key, self::defaultCountry());
83
    }
84
85
    /**
86
     * Return default country code.
87
     *
88
     * @return string
89
     */
90 View Code Duplication
    public static function defaultCountry(): string
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
91
    {
92
        $default = Cache::get('country_default');
93
94
        if ($default === null)
95
        {
96
            $default = static::query()
0 ignored issues
show
Bug introduced by
The method select() does not exist on Illuminate\Database\Eloquent\Builder. Did you maybe mean createSelectWithConstraint()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
97
                ->select('country')
98
                ->where('is_default', '=', true)
99
                ->first();
100
            $default = !empty($default) ? $default->country : config('contentful.default_country');
101
            // Cache is cleaned in Console\Commands\SyncLocales (run at least daily)
102
            Cache::forever('country_default', $default);
103
        }
104
105
        return $default;
106
    }
107
108
    /**
109
     * Return fallback code for given locale code.
110
     *
111
     * @param  string $code
112
     * @return string
113
     */
114
    public static function fallback(string $code): string
115
    {
116
        $fallback = Cache::get('locale_fallback_' . $code);
117
118
        if ($fallback === null)
119
        {
120
            $locale = static::query()
0 ignored issues
show
Bug introduced by
The method select() does not exist on Illuminate\Database\Eloquent\Builder. Did you maybe mean createSelectWithConstraint()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
121
                ->select('fallback_code')
122
                ->where('code', '=', $code)
123
                ->first();
124
125
            $fallback = (!empty($locale) and !empty($locale->fallback_code)) ? $locale->fallback_code : '';
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
126
127
            Cache::put('locale_fallback_' . $code, $fallback, 5);
128
        }
129
130
        return $fallback;
131
    }
132
133
    public static function canBeSave(string $country, string $locale): bool
134
    {
135
        return !in_array($country . '_' . $locale, static::_getLocalesDisabled());
136
    }
137
138
    protected static function _getLocalesDisabled(): array
139
    {
140
        $locales = config('contentful.locales_not_flatten', '');
141
        return explode(',', $locales);
142
    }
143
144
    public function isEnabled(): bool
145
    {
146
        return !in_array($this->country . '_' . $this->locale, static::_getLocalesDisabled());
147
    }
148
149 View Code Duplication
    public static function getLocale(string $locale): string
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
150
    {
151
        if (Str::contains($locale, '_'))
152
        {
153
            $tab = explode('_', $locale);
154
            return $tab[1];
155
        } else if (Str::contains($locale, '-'))
156
        {
157
            $tab = explode('-', $locale);
158
            return $tab[1];
159
        }
160
161
        return $locale;
162
    }
163
164 View Code Duplication
    public static function getCountry(string $locale): string
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
165
    {
166
        if (Str::contains($locale, '_'))
167
        {
168
            $tab = explode('_', $locale);
169
            return $tab[0];
170
        } else if (Str::contains($locale, '-'))
171
        {
172
            $tab = explode('-', $locale);
173
            return $tab[0];
174
        }
175
176
        return config('contentful.default_country');
177
    }
178
179
180
    /**
181
     * Return request accepted languages.
182
     *
183
     * @param  \Illuminate\Http\Request|null $request
184
     * @return string|array
185
     */
186
    public static function getAcceptedLanguages(Request $request = null)
187
    {
188
        $request = !empty($request) ? $request : request();
189
190
        $langs = $request->server('HTTP_ACCEPT_LANGUAGE');
191
        if (!empty($langs))
192
        {
193
            preg_match_all('/(\W|^)([a-z]{2})([^a-z]|$)/six', $langs, $locales, PREG_PATTERN_ORDER);
194
195
            if (!empty($locales) and !empty($locales[2]))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
196
            {
197
                return $locales[2];
198
            }
199
        }
200
201
        return [];
202
    }
203
204
    /**
205
     * Return user default language.
206
     *
207
     * @param  \Illuminate\Http\Request|null $request
208
     * @return string
209
     */
210
    public static function getDefaultLanguageUser(Request $request = null): string
211
    {
212
        $country = self::defaultCountry();
213
        $locales = static::getAcceptedLanguages($request);
214
        $locale = !empty($locales) ? $locales[0] : config('app.fallback_locale');
215
216
        $localeModel = (new static)
217
            ->where('country', $country)
218
            ->where('locale', $locale)
219
            ->take(1)
220
            ->get()
221
            ->firs();
222
223
        return empty($localeModel) ? static::default() : $localeModel->locale;
224
    }
225
226
227
}
228