Passed
Push — master ( b59491...180d95 )
by Thomas
03:05
created

LangHelper::persistLocaleIfCookiesAreAllowed()   C

Complexity

Conditions 12
Paths 39

Size

Total Lines 59
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 12
eloc 36
c 1
b 0
f 1
nc 39
nop 0
dl 0
loc 59
rs 6.9666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace LeKoala\Multilingual;
4
5
use Exception;
6
use SilverStripe\Admin\LeftAndMain;
7
use SilverStripe\Control\Controller;
8
use SilverStripe\i18n\i18n;
9
use SilverStripe\Control\Cookie;
10
use SilverStripe\Control\Session;
11
use SilverStripe\Control\Director;
12
use TractorCow\Fluent\Model\Locale;
0 ignored issues
show
Bug introduced by
The type TractorCow\Fluent\Model\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...
13
use SilverStripe\Core\Config\Config;
14
use TractorCow\Fluent\State\FluentState;
0 ignored issues
show
Bug introduced by
The type TractorCow\Fluent\State\FluentState 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...
15
use SilverStripe\Core\Config\Configurable;
16
17
/**
18
 * i18n helper class
19
 */
20
class LangHelper
21
{
22
    use Configurable;
23
24
    /**
25
     * The default key for global translation
26
     */
27
    const GLOBAL_ENTITY = 'Global';
28
29
    /**
30
     * Provision fluent locales defined in yml
31
     * Use LangHelper::provisionLocales
32
     *
33
     * eg:
34
     * LeKoala\Base\i18n\BaseI18n:
35
     *   default_locales:
36
     *     - en_US
37
     *     - fr_FR
38
     * @config
39
     * @var array
40
     */
41
    private static $default_locales = [];
42
43
    /**
44
     * @config
45
     * @var boolean
46
     */
47
    private static $persist_cookie = true;
48
49
    /**
50
     * @var array
51
     */
52
    protected static $locale_cache = [];
53
54
    /**
55
     * Get a global translation
56
     *
57
     * By default all global translation are stored under the Global key
58
     *
59
     * @param string $entity If no entity is specified, Global is assumed
60
     * @return string
61
     */
62
    public static function globalTranslation($entity)
63
    {
64
        $parts = explode('.', $entity);
65
        if (count($parts) == 1) {
66
            array_unshift($parts, self::GLOBAL_ENTITY);
67
        }
68
        return i18n::_t(implode('.', $parts), $entity);
69
    }
70
71
    /**
72
     * Call this to make sure we are not setting any cookies that has
73
     * not been accepted
74
     *
75
     * @return void
76
     */
77
    public static function persistLocaleIfCookiesAreAllowed()
78
    {
79
        if (headers_sent()) {
80
            return;
81
        }
82
83
        $class = \TractorCow\Fluent\Middleware\DetectLocaleMiddleware::class;
0 ignored issues
show
Bug introduced by
The type TractorCow\Fluent\Middle...\DetectLocaleMiddleware 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...
84
        if (!class_exists($class)) {
85
            return;
86
        }
87
88
        $persist = static::config()->persist_cookie;
89
        if (!$persist) {
90
            return;
91
        }
92
93
        // If we choose to persist cookies, we should check our cookie consent first
94
        $dont_persist = true;
95
        // cookie consent from osano
96
        $status = Cookie::get('cookieconsent_status');
97
        if (strlen($status) && $status == 'allow') {
0 ignored issues
show
Bug introduced by
It seems like $status can also be of type null; however, parameter $string of strlen() 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

97
        if (strlen(/** @scrutinizer ignore-type */ $status) && $status == 'allow') {
Loading history...
98
            $dont_persist = false;
99
        }
100
        // cookie from cookieconsent
101
        $status = Cookie::get('cookie_consent_user_accepted');
102
        if (strlen($status) && $status == 'true') {
103
            $dont_persist = false;
104
        }
105
106
        if ($dont_persist) {
107
            return;
108
        }
109
110
        // Persist according to fluent settings
111
        $curr = Controller::curr();
112
        $request = $curr->getRequest();
113
114
        $secure = Director::is_https($request)
115
            && Session::config()->get('cookie_secure');
116
117
        $persistIds = $class::config()->get('persist_ids');
118
        $persistKey = FluentState::singleton()->getIsFrontend()
119
            ? $persistIds['frontend']
120
            : $persistIds['cms'];
121
122
        $locale = $request->getSession()->get($persistKey);
123
        // If session is not started or set, it may not be set
124
        if (!$locale) {
125
            $locale = self::get_locale();
126
        }
127
128
        Cookie::set(
129
            $persistKey,
130
            $locale,
131
            $class::config()->get('persist_cookie_expiry'),
132
            $class::config()->get('persist_cookie_path'),
133
            $class::config()->get('persist_cookie_domain'),
134
            $secure,
135
            $class::config()->get('persist_cookie_http_only')
136
        );
137
    }
138
139
    /**
140
     * Provision locales defined in default_locales
141
     *
142
     * @return void
143
     */
144
    public static function provisionLocales()
145
    {
146
        $locales = self::config()->default_locales;
147
        if (empty($locales)) {
148
            throw new Exception("No locales defined in BaseI18n:default_locales");
149
        }
150
151
        foreach ($locales as $loc) {
152
            $Locale = Locale::get()->filter('Locale', $loc)->first();
153
            $allLocales = i18n::getData()->getLocales();
154
            if (!$Locale) {
155
                $Locale = new Locale();
156
                $Locale->Title = $allLocales[$loc];
157
                $Locale->Locale = $loc;
158
                $Locale->URLSegment = self::get_lang($loc);
159
                $Locale->IsGlobalDefault = $loc == i18n::get_locale();
160
                $Locale->write();
161
            }
162
        }
163
    }
164
165
    /**
166
     * Make sure we get a proper two characters lang
167
     *
168
     * @param string|object $lang a string or a fluent locale object
169
     * @return string a two chars lang
170
     */
171
    public static function get_lang($lang = null)
172
    {
173
        if (!$lang) {
174
            $lang = self::get_locale();
175
        }
176
        if (is_object($lang)) {
177
            $lang = $lang->Locale;
178
        }
179
        return substr($lang, 0, 2);
180
    }
181
182
    /**
183
     * Get the right locale (using fluent data if exists)
184
     *
185
     * @return string
186
     */
187
    public static function get_locale()
188
    {
189
        if (class_exists(FluentState::class)) {
190
            $locale = FluentState::singleton()->getLocale();
191
            // Locale may not be set, in tests for instance
192
            if ($locale) {
193
                return $locale;
194
            }
195
        }
196
        return i18n::get_locale();
197
    }
198
199
    /**
200
     * Get a locale from the lang
201
     *
202
     * @param string $lang
203
     * @return string
204
     */
205
    public static function get_locale_from_lang($lang)
206
    {
207
        // Use fluent data
208
        if (class_exists(Locale::class)) {
209
            if (empty(self::$locale_cache)) {
210
                $fluentLocales = Locale::getLocales();
211
                foreach ($fluentLocales as $locale) {
212
                    self::$locale_cache[self::get_lang($locale->Locale)] = $locale->Locale;
213
                }
214
            }
215
            if (isset(self::$locale_cache[$lang])) {
216
                return self::$locale_cache[$lang];
217
            }
218
        }
219
        // Guess
220
        $localesData = i18n::getData();
221
        return $localesData->localeFromLang($lang);
222
    }
223
224
    /**
225
     * Do we have the subsite module installed
226
     * TODO: check if it might be better to use module manifest instead?
227
     *
228
     * @return bool
229
     */
230
    public static function usesFluent()
231
    {
232
        return class_exists(FluentState::class);
233
    }
234
235
    /**
236
     * @return array
237
     */
238
    public static function get_available_langs()
239
    {
240
        if (!self::usesFluent()) {
241
            return [
242
                self::get_lang()
243
            ];
244
        }
245
246
        $allLocales = Locale::get();
247
        $results = [];
248
        foreach ($allLocales as $locale) {
249
            $results[] = $locale->URLSegment;
250
        }
251
        return $results;
252
    }
253
254
    /**
255
     * Execute the callback in given subsite
256
     *
257
     * @param string $locale
258
     * @param callable $cb
259
     * @return mixed the callback result
260
     */
261
    public static function withLocale($locale, $cb)
262
    {
263
        if (!self::usesFluent() || !$locale) {
264
            $cb();
265
            return;
266
        }
267
        if (!is_string($locale)) {
0 ignored issues
show
introduced by
The condition is_string($locale) is always true.
Loading history...
268
            $locale = $locale->Locale;
269
        }
270
        $state = FluentState::singleton();
271
        return $state->withState(function ($state) use ($locale, $cb) {
272
            $state->setLocale($locale);
273
            return $cb();
274
        });
275
    }
276
277
    /**
278
     * Execute the callback for all locales
279
     *
280
     * @param callable $cb
281
     * @return array an array of callback results
282
     */
283
    public static function withLocales($cb)
284
    {
285
        if (!self::usesFluent()) {
286
            $cb();
287
            return [];
288
        }
289
        $allLocales = Locale::get();
290
        $results = [];
291
        foreach ($allLocales as $locale) {
292
            $results[] = self::withLocale($locale, $cb);
293
        }
294
        return $results;
295
    }
296
}
297