Issues (18)

Lezer.php (18 issues)

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) {
0 ignored issues
show
The type HexMakina\Lezer\Dato 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...
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()) {
0 ignored issues
show
The method isInitialized() 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

127
        if ($this->/** @scrutinizer ignore-call */ isInitialized()) {

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...
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;
0 ignored issues
show
Bug Best Practice introduced by
The property isInitialized does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
132
133
        $this->userLangs = $this->getUserLangs();
0 ignored issues
show
The method getUserLangs() 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

133
        /** @scrutinizer ignore-call */ 
134
        $this->userLangs = $this->getUserLangs();

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...
Bug Best Practice introduced by
The property userLangs does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
134
135
        // search for language file
136
        $this->appliedLang = NULL;
0 ignored issues
show
Bug Best Practice introduced by
The property appliedLang does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
137
        foreach ($this->userLangs as $priority => $langcode) {
138
            $this->langFilePath = $this->getConfigFilename($langcode);
0 ignored issues
show
Bug Best Practice introduced by
The property langFilePath does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
The method getConfigFilename() 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

138
            /** @scrutinizer ignore-call */ 
139
            $this->langFilePath = $this->getConfigFilename($langcode);

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...
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';
0 ignored issues
show
Bug Best Practice introduced by
The property prefix does not exist on HexMakina\Lezer\Lezer. Did you maybe forget to declare it?
Loading history...
The property cachePath does not exist on HexMakina\Lezer\Lezer. Did you mean cacheFilePath?
Loading history...
Bug Best Practice introduced by
The property cacheFilePath does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
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
0 ignored issues
show
Bug Best Practice introduced by
The property mergeFallback does not exist on HexMakina\Lezer\Lezer. Did you maybe forget to declare it?
Loading history...
Bug Best Practice introduced by
The property fallbackLang does not exist on HexMakina\Lezer\Lezer. Did you maybe forget to declare it?
Loading history...
155
156
        if ($outdated) {
157
            $config = $this->load($this->langFilePath);
0 ignored issues
show
The method load() 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

157
            /** @scrutinizer ignore-call */ 
158
            $config = $this->load($this->langFilePath);

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...
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)
0 ignored issues
show
The method compile() does not exist on HexMakina\Lezer\Lezer. Did you maybe mean compileFunction()? ( Ignorable by Annotation )

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

162
            	. $this->/** @scrutinizer ignore-call */ compile($config)

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...
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"
0 ignored issues
show
Bug Best Practice introduced by
The property prefix does not exist on HexMakina\Lezer\Lezer. Did you maybe forget to declare it?
Loading history...
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);
0 ignored issues
show
Bug Best Practice introduced by
The property prefix does not exist on HexMakina\Lezer\Lezer. Did you maybe forget to declare it?
Loading history...
204
    }
205
}
206