Issues (18)

Lezer.php (1 issue)

1
<?php
2
3
/**
4
 * honnors Ludwik *Lejzer* Zamenhof (Polish: Ludwik Łazarz Zamenhof);
5
 * 15 December [O.S. 3 December] 1859 – 14 April [O.S. 1 April] 1917),
6
 * a medical doctor, inventor, and writer; most widely known for creating Esperanto.
7
 *
8
 * also Lezer is dutch for Reader, and it sounds like LASER, which is kinda cool.
9
 */
10
namespace HexMakina\Lezer;
11
12
class Lezer
13
{
14
    private $translations = [];
15
  
16
    public function __construct(string $pathToTranslations) {
17
        if (file_exists($pathToTranslations)) {
18
            $json = file_get_contents($pathToTranslations);
19
            $this->translations = json_decode($json, true) ?: [];
20
        }
21
    }
22
23
24
    public function l(string $key, array $context = []): string
25
    {
26
        // no translation available, returns the key
27
        $translation = $this->translations[$key] ?? null;
28
29
        if (empty($translation)) {
30
            return $key;
31
        }
32
    
33
        // translate context
34
        if (empty($context)) {
35
            return $translation;
36
        }
37
    
38
        return vsprintf($translation, array_map([$this, 'l'], $context));
39
    }
40
41
    /**
42
     * Provides a method to detect languages that is requested from the client.
43
     * First it looks for the language values in $_GET, $_SESSION and $_COOKIE. 
44
     * For each found language, it assigns a quality value
45
     *      1000 for $_GET, 
46
     *      100 for $_SESSION and 
47
     *      10 for $_COOKIE
48
     * 
49
     * If no languages are found, it calls parseHTTPHeader()
50
     * 
51
     * Then it removes duplicates and sorts the array of detected languages by Quality, 
52
     * highest first
53
     *
54
     * @return array with the user languages sorted by priority.
55
     */
56
57
    public static function detectLanguages($key='lang') : array
58
    {
59
        $ret = [];
60
        foreach(['$_GET' => 1000, '$_SESSION' => 100, '$_COOKIE' => 10] as $source => $quality){
61
            $lang = $$source[$key] ?? null;
62
            if(!empty($lang) && preg_match('/^[a-zA-Z0-9_-]*$/', $lang) === 1){
63
                $ret[$quality] = $lang;
64
            }
65
        }
66
67
        if(empty($ret))
68
            $ret = self::parseHTTPHeader();
0 ignored issues
show
The method parseHTTPHeader() does not exist on HexMakina\Lezer\Lezer. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

68
            /** @scrutinizer ignore-call */ 
69
            $ret = self::parseHTTPHeader();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
69
70
        $ret = array_unique($ret);
71
        // Sort the detected languages by quality, with the highest quality first
72
        arsort($ret);
73
74
        return $ret;
75
    }
76
77
    public function time($time_string, $short = true)
78
    {
79
        if ($short === true) {
80
            $time_string = substr($time_string, 0, 5);
81
        }
82
        return $time_string;
83
    }
84
85
    public function date($date_string, $short = true)
86
    {
87
        if ($date_string === '0000-00-00' || empty($date_string)) {
88
            return $this->l('MODEL_common_VALUE_EMPTY');
89
        }
90
91
        if (preg_match('/^[0-9]{4}$/', $date_string) === 1) {
92
            return intval($date_string);
93
        }
94
95
        list($year, $month, $day) = explode('-', $date_string);
96
97
        $ret = intval($day) . ' ' . $this->l("DATETIME_CALENDAR_MONTH_$month");
98
99
        if ($short === true && Dato::format(null, 'Y') === $year) {
100
            return $ret;
101
        } else {
102
            return "$ret $year";
103
        }
104
    }
105
106
    public function month($date_string)
107
    {
108
        return $this->l('DATETIME_CALENDAR_MONTH_' . Dato::format($date_string, 'm'));
109
    }
110
111
    public function day($date_string)
112
    {
113
        return $this->l('DATETIME_CALENDAR_DAY_' . Dato::format($date_string, 'N'));
114
    }
115
116
    public function seconds($seconds)
117
    {
118
        $hours = floor($seconds / 3600);
119
        $mins = floor(($seconds - $hours * 3600) / 60);
120
        $secs = floor($seconds % 60);
121
122
        $hours_format = '%dh %dm %ds';
123
        return sprintf($hours_format, $hours, $mins, $secs);
124
    }
125
126
    public function init() {
127
        if ($this->isInitialized()) {
128
            throw new \BadMethodCallException('This object from class ' . __CLASS__ . ' is already initialized. It is not possible to init one object twice!');
129
        }
130
131
        $this->isInitialized = true;
132
133
        $this->userLangs = $this->getUserLangs();
134
135
        // search for language file
136
        $this->appliedLang = NULL;
137
        foreach ($this->userLangs as $priority => $langcode) {
138
            $this->langFilePath = $this->getConfigFilename($langcode);
139
            if (file_exists($this->langFilePath)) {
140
                $this->appliedLang = $langcode;
141
                break;
142
            }
143
        }
144
        if ($this->appliedLang == NULL) {
145
            throw new \RuntimeException('No language file was found.');
146
        }
147
148
        // search for cache file
149
        $this->cacheFilePath = $this->cachePath . '/php_i18n_' . md5_file(__FILE__) . '_' . $this->prefix . '_' . $this->appliedLang . '.cache.php';
150
151
        // whether we need to create a new cache file
152
        $outdated = !file_exists($this->cacheFilePath) ||
153
            filemtime($this->cacheFilePath) < filemtime($this->langFilePath) || // the language config was updated
154
            ($this->mergeFallback && filemtime($this->cacheFilePath) < filemtime($this->getConfigFilename($this->fallbackLang))); // the fallback language config was updated
155
156
        if ($outdated) {
157
            $config = $this->load($this->langFilePath);
158
            if ($this->mergeFallback)
159
                $config = array_replace_recursive($this->load($this->getConfigFilename($this->fallbackLang)), $config);
160
161
            $compiled = "<?php class " . $this->prefix . " {\n"
162
            	. $this->compile($config)
163
            	. 'public static function __callStatic($string, $args) {' . "\n"
164
            	. '    return vsprintf(constant("self::" . $string), $args);'
165
            	. "\n}\n}\n"
166
              . $this->compileFunction();
167
168
			if( ! is_dir($this->cachePath))
169
				mkdir($this->cachePath, 0755, true);
170
171
            if (file_put_contents($this->cacheFilePath, $compiled) === FALSE) {
172
                throw new \Exception("Could not write cache file to path '" . $this->cacheFilePath . "'. Is it writable?");
173
            }
174
            try{
175
                chmod($this->cacheFilePath, 0755);
176
              }
177
              catch(\Throwable $t){
178
                throw new \Exception("Could chmod cache file '" . $this->cacheFilePath . "'");
179
              }
180
181
182
        }
183
184
        require_once $this->cacheFilePath;
185
    }
186
187
    public function compileFunction()
188
    {
189
        return ''
190
        . "function " . $this->prefix . '($string, $args=NULL) {' . "\n"
191
        . '    if (!defined("' . $this->prefix . '::".$string))'
192
        . '       return $string;'
193
        . '    $return = constant("' . $this->prefix . '::".$string);' . "\n"
194
        . '    return $args ? vsprintf($return,$args) : $return;'
195
        . "\n}";
196
    }
197
198
    public function l($message, $context = []): string
199
    {
200
        foreach($context as $i => $context_message)
201
          $context[$i] = $this->l($context_message);
202
203
        return call_user_func($this->prefix, $message, $context);
204
    }
205
}
206