Passed
Push — master ( 2b1ac9...97cf13 )
by Mihail
02:13
created

I18nCatalog   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 102
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 31
c 3
b 0
f 0
dl 0
loc 102
ccs 34
cts 34
cp 1
rs 10
wmc 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A new() 0 19 3
A __construct() 0 8 1
A normalizeLocale() 0 8 2
A translate() 0 9 1
A formatter() 0 3 1
A directory() 0 3 1
A locale() 0 3 1
1
<?php
2
3
namespace Koded\I18n;
4
5
use Koded\Stdlib\Configuration;
6
use Throwable;
7
use function array_key_exists;
8
use function getcwd;
9
use function rtrim;
10
11
abstract class I18nCatalog
12
{
13
    protected string $locale;
14
    protected string $directory;
15
    protected I18nFormatter $formatter;
16
17 17
    private function __construct(
18
        I18nFormatter $formatter,
19
        string        $directory,
20
        string        $locale)
21
    {
22 17
        $this->formatter = $formatter;
23 17
        $this->directory = rtrim($directory, '/');
24 17
        $this->locale = $this->initialize($locale);
25 17
    }
26
27 17
    public static function new(Configuration $conf): I18nCatalog
28
    {
29 17
        $catalog = $conf->get('translation.catalog', ArrayCatalog::class);
30 17
        $formatter = $conf->get('translation.formatter', DefaultFormatter::class);
31 17
        $instance = new $catalog(
32 17
            new $formatter,
33 17
            $directory = $conf->get('translation.dir', getcwd() . '/locales'),
34 17
            $locale = self::normalizeLocale($conf->get('translation.locale', I18n::DEFAULT_LOCALE))
35
        );
36 17
        if ($instance->supports($locale)) {
37 15
            return $instance;
38
        }
39 7
        if ($catalog !== ArrayCatalog::class) {
40 2
            error_log(" > ($locale) gettext not supported, trying ArrayCatalog ...");
41 2
            $conf->set('translation.catalog', ArrayCatalog::class);
42 2
            return static::new($conf);
43
        }
44
        // Last resort, passthru
45 6
        return new NoCatalog(new $formatter, $directory, $locale);
46
    }
47
48 17
    public static function normalizeLocale(string $locale): string
49
    {
50 17
        $locale = str_replace('.', '_', $locale);
51 17
        if (substr_count($locale, '_') > 1) {
52 1
            $locale = explode('_', $locale);
53 1
            $locale = "$locale[0]_$locale[1]";
54
        }
55 17
        return $locale;
56
    }
57
58 9
    public function translate(
59
        string $domain,
60
        string $key,
61
        array  $arguments = [],
62
        int    $n = 0): string
63
    {
64 9
        return $this->formatter->format(
65 9
            $this->message($domain, $key, $n),
66
            $arguments
67
        );
68
    }
69
70 17
    public function locale(): string
71
    {
72 17
        return $this->locale;
73
    }
74
75 17
    public function directory(): string
76
    {
77 17
        return $this->directory;
78
    }
79
80 17
    public function formatter(): I18nFormatter
81
    {
82 17
        return $this->formatter;
83
    }
84
85
    /**
86
     * Translates the message.
87
     *
88
     * @param string $domain
89
     * @param string $string
90
     * @param int $n
91
     * @return string
92
     */
93
    abstract protected function message(string $domain, string $string, int $n): string;
94
95
    /**
96
     * Checks if the locale is supported for this catalog,
97
     * or other specific requirements.
98
     *
99
     * @param string $locale
100
     * @return bool
101
     */
102
    abstract protected function supports(string $locale): bool;
103
104
    /**
105
     * Initialize the catalog object. This method is
106
     * called before supports().
107
     *
108
     * @param string $locale Desired locale to be initialized
109
     * @return string|false Returns the set locale,
110
     *                      or FALSE if initialization fails.
111
     */
112
    abstract protected function initialize(string $locale): string|false;
113
}
114
115
class NoCatalog extends I18nCatalog
116
{
117 4
    protected function message(string $domain, string $string, int $n): string
118
    {
119 4
        return $string;
120
    }
121
122
    // @codeCoverageIgnoreStart
123
    protected function supports(string $locale): bool
124
    {
125
        return true;
126
    }
127
128
    // @codeCoverageIgnoreEnd
129
130 7
    protected function initialize(string $locale): string|false
131
    {
132 7
        return $locale;
133
    }
134
}
135
136
class ArrayCatalog extends I18nCatalog
137
{
138
    private array $data = [];
139
140 4
    protected function message(string $domain, string $string, int $n): string
141
    {
142 4
        return $this->data[$domain][$string] ?? $string;
143
    }
144
145 15
    protected function supports(string $locale): bool
146
    {
147 15
        return $this->locale === $locale;
148
    }
149
150 15
    protected function initialize(string $locale): string|false
151
    {
152
        try {
153 15
            $this->data = require($catalog = "$this->directory/$locale.php");
154 12
            if (false === array_key_exists('messages', $this->data)) {
155 1
                error_log("ERROR : i18n catalog $catalog is missing the messages array");
156 1
                return false;
157
            }
158 12
            return $locale;
159 5
        } catch (Throwable $e) {
160 5
            error_log($e->getMessage());
161 5
            return false;
162
        }
163
    }
164
}
165