Passed
Push — development ( 2bb3b4...48f606 )
by Emanuele
53s
created

Lang::loadLang()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 26
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 4

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 26
rs 8.5806
ccs 14
cts 14
cp 1
cc 4
eloc 10
nc 4
nop 1
crap 4
1
<?php
2
/**
3
 * @name      OpenImporter
4
 * @copyright OpenImporter contributors
5
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
6
 *
7
 * @version 2.0 Alpha
8
 */
9
10
namespace OpenImporter\Core;
11
12
/**
13
 * Class Lang
14
 * loads the appropriate language file(s) if they exist.
15
 *
16
 * The default import_en.xml file contains the English strings used by the
17
 * importer.
18
 */
19
class Lang
20
{
21
	/**
22
	 * The array holding the strings
23
	 *
24
	 * @var string[]
25
	 */
26
	protected $_lang = array();
27
28
	/**
29
	 * Loads the language xml file.
30
	 *
31
	 * @param string $path
32
	 *
33
	 * @throws \Exception if it cannot find the XML file.
34
	 * @throws ImportException if the XML file has got a corrupted structure.
35
	 */
36 3
	public function loadLang($path)
37
	{
38
		// Detect the browser language
39 3
		$language = $this->detectBrowserLanguage();
40 3
		$language_file = $this->findLanguage($path, $language);
41
42
		// Ouch, we really should never arrive here..
43 3
		if (!$language_file)
44 3
		{
45 1
			throw new \Exception('Unable to detect language file!');
46
		}
47
48
		// Silence simplexml errors because we take care of them by ourselves
49 2
		libxml_use_internal_errors(true);
50
51
		// Load the language file
52 2
		if (!$langObj = simplexml_load_file($language_file, 'SimpleXMLElement', LIBXML_NOCDATA))
53 2
		{
54 1
			throw new ImportException('XML-Syntax error in file: ' . $language_file);
55
		}
56
57 1
		foreach ($langObj as $strings)
58
		{
59 1
			$this->set((string) $strings->attributes()->{'name'}, (string) $strings);
60 1
		}
61 1
	}
62
63
	/**
64
	 * This is used to detect the Client's browser language.
65
	 *
66
	 * @return string[] the shortened string of the browser's language.
67
	 */
68 3
	protected function detectBrowserLanguage()
0 ignored issues
show
Coding Style introduced by
detectBrowserLanguage uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
69
	{
70 3
		$preferred = array();
71
72 3
		if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
73 3
		{
74
			// Break up string into pieces (languages and q factors)
75
			// the string looks like: en-GB,en;q=0.9,it;q=0.8
76 3
			preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']), $lang_parse);
77
78 3
			if (count($lang_parse[1]))
79 3
			{
80
				// Create a list like "en" => 0.8
81 3
				$preferred = array_combine($lang_parse[1], $lang_parse[4]);
82
83
				// Set default to 1 for any without q factor (IE fix)
84 3
				foreach ($preferred as $lang => $val)
85
				{
86 3
					if ($val === '')
87 3
					{
88 2
						$preferred[$lang] = 1;
89 2
					}
90 3
				}
91
92
				// Sort list based on value
93 3
				arsort($preferred, SORT_NUMERIC);
94 3
			}
95 3
		}
96
97 3
		return array_keys($preferred);
98
	}
99
100
	/**
101
	 * Finds out if the language we are looking for exists or not.
102
	 *
103
	 * @param string $path The path to look for the language file
104
	 * @param string[] $language The name of the language
105
	 *
106
	 * @return bool
107
	 */
108 4
	protected function findLanguage($path, $language)
109
	{
110 4
		$language_file = false;
111
112
		// Loop through the preferred languages and try to find the related language file
113 4
		foreach ($language as $key)
114
		{
115 4
			if (file_exists($path . '/import_' . $key . '.xml'))
116 4
			{
117 3
				$language_file = $path . '/import_' . $key . '.xml';
118 3
				break;
119
			}
120 4
		}
121
122
		// English is still better than nothing
123 4
		if (empty($language_file))
124 4
		{
125 2
			if (file_exists($path . '/import_en.xml'))
126 2
			{
127 1
				$language_file = $path . '/import_en.xml';
128 1
			}
129 2
		}
130
131 4
		return $language_file;
132
	}
133
134
	/**
135
	 * Adds a new variable to lang.
136
	 *
137
	 * @param string $key Name of the variable
138
	 * @param string $value Value of the variable
139
	 *
140
	 * @throws \Exception
141
	 * @return boolean|null
142
	 */
143 5
	protected function set($key, $value)
144
	{
145
		try
146
		{
147 5
			if ($this->has($key))
148 5
			{
149 1
				throw new \Exception('Unable to set language string for <em>' . $key . '</em>. It was already set.');
150
			}
151
152 5
			$this->_lang[$key] = $value;
153
154 5
			return true;
155
		}
156 1
		catch (Exception $e)
157
		{
158
			// @todo this should not be a fatal error
159
			ImportException::exceptionHandler($e);
160
		}
161
	}
162
163
	/**
164
	 * Tests if given $key exists in lang
165
	 *
166
	 * @param string $key
167
	 *
168
	 * @return bool
169
	 */
170 4
	public function has($key)
171
	{
172 4
		return isset($this->_lang[$key]);
173
	}
174
175
	/**
176
	 * Getter
177
	 *
178
	 * @param string|int $key
179
	 *
180
	 * @return string|int|bool|null|object
181
	 */
182 1
	public function __get($key)
183
	{
184 1
		return $this->get($key);
185
	}
186
187
	/**
188
	 * Returns the value of the specified $key in lang.
189
	 *
190
	 * @param string|mixed[] $key Name of the variable
191
	 *
192
	 * @return string|null Value of the specified $key
193
	 */
194 1
	public function get($key)
195
	{
196 1
		if (is_array($key))
197 1
		{
198 1
			$l_key = array_shift($key);
199
200 1
			if ($this->has($l_key))
201 1
			{
202 1
				return vsprintf($this->_lang[$l_key], $key);
203
			}
204
			else
205
			{
206 1
				return array_pop($key);
207
			}
208
		}
209
		else
210
		{
211 1
			if ($this->has($key))
212 1
			{
213 1
				return $this->_lang[$key];
214
			}
215
			else
216
			{
217 1
				return $key;
218
			}
219
		}
220
	}
221
222
	/**
223
	 * Tests if the key is set.
224
	 *
225
	 * @param string|int $key
226
	 *
227
	 * @return bool
228
	 */
229
	public function __isset($key)
230
	{
231
		return array_key_exists($key, $this->_lang);
232
	}
233
234
	/**
235
	 * Returns the whole lang as an array.
236
	 *
237
	 * @return array Whole lang
238
	 */
239 1
	public function getAll()
240
	{
241 1
		return $this->_lang;
242
	}
243
}