LocaleLoader::getActualDomain()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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