Completed
Push — master ( 41d494...65eac1 )
by Mārtiņš
02:03
created

LocaleLoader::setLocale()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0175

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 7
cts 8
cp 0.875
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 1
crap 3.0175
1
<?php
2
3
namespace Printful\GettextCms;
4
5
use Printful\GettextCms\Exceptions\UnsupportedLocaleException;
6
use Printful\GettextCms\Interfaces\MessageConfigInterface;
7
8
/**
9
 * Class sets locales and binds domains for current request
10
 */
11
class LocaleLoader
12
{
13
    /** @var MessageConfigInterface */
14
    private $config;
15
16
    /** @var MessageRevisions */
17
    private $revisions;
18
19 1
    public function __construct(MessageConfigInterface $config)
20
    {
21 1
        $this->revisions = new MessageRevisions($config);
22 1
        $this->config = $config;
23 1
    }
24
25
    /**
26
     * Globally set current locale and bind gettext domains
27
     *
28
     * @param string $locale
29
     * @return bool If false is returned, some domains may not have been bound and will fail
30
     * @throws UnsupportedLocaleException
31
     */
32 1
    public function load(string $locale): bool
33
    {
34 1
        putenv("LANG=" . $locale);
35
36
        // Some systems use LANGUAGE variant above LANG, so we just set both of them, just in case.
37 1
        putenv("LANGUAGE=" . $locale);
38
39 1
        if (!$this->setLocale($locale)) {
40
            throw new UnsupportedLocaleException('Locale is not supported by your system: ' . $locale);
41
        }
42
43 1
        return $this->bindDomains($locale);
44
    }
45
46 1
    private function setLocale($locale): bool
47
    {
48
        // Some locales contain utf postfix, so we should try them all
49
        $locales = [
50 1
            $locale,
51 1
            $locale . '.utf8',
52 1
            $locale . '.UTF-8',
53
        ];
54
55 1
        foreach ($locales as $v) {
56 1
            if (setlocale(LC_ALL, $v)) {
57 1
                return true;
58
            }
59
        }
60
61
        return false;
62
    }
63
64
    /**
65
     * Bind all domains for locale
66
     *
67
     * @param string $locale
68
     * @return bool Returns false if binding fails, translations may not work correctly
69
     */
70 1
    private function bindDomains(string $locale): bool
71
    {
72 1
        $domainBound = true;
73
74 1
        $domainDir = rtrim($this->config->getMoDirectory(), '/');
75
76 1
        $defaultDomain = $this->config->getDefaultDomain();
77
78 1
        $allDomains = $this->config->getOtherDomains();
79 1
        $allDomains[] = $defaultDomain;
80
81 1
        foreach ($allDomains as $domain) {
82 1
            $actualDomain = $this->getActualDomain($locale, $domain);
83
84
            // File structure for a translation is: mo-directory/{locale}/LC_MESSAGES/{domain}.mo
85 1
            if (!bindtextdomain($actualDomain, $domainDir)) {
86
                // If text domain binding fails, something is wrong with the paths
87
                $domainBound = false;
88
            }
89
90 1
            bind_textdomain_codeset($actualDomain, 'utf8');
91
        }
92
93
        // Bind the default domain for _() calls (and other non-domain specific calls)
94 1
        textdomain($this->getActualDomain($locale, $defaultDomain));
95
96 1
        return $domainBound;
97
    }
98
99
    /**
100
     * Get actual domain name. If revisions are enabled, this will return something like "domain_xxxxxx"
101
     *
102
     * @param string $locale
103
     * @param string $domain
104
     * @return string
105
     */
106 1
    private function getActualDomain(string $locale, string $domain): string
107
    {
108 1
        if ($this->config->useRevisions()) {
109
            return $this->revisions->getRevisionedDomain($locale, $domain);
110
        }
111
112 1
        return $domain;
113
    }
114
}