[BUGFIX] L10n PHP parser stores NULL for unknown key
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Localization / Parser / LocallangArrayParser.php
1 <?php
2 namespace TYPO3\CMS\Core\Localization\Parser;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2011 Dominique Feyer <dfeyer@reelpeek.net>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /**
30 * Parser for PHP locallang array.
31 *
32 * @package TYPO3
33 * @subpackage t3lib
34 * @author Dominique Feyer <dfeyer@reelpeek.net>
35 * @author Dmitry Dulepov <dmitry.dulepov@gmail.com>
36 */
37 class LocallangArrayParser implements \TYPO3\CMS\Core\Localization\Parser\LocalizationParserInterface {
38
39 /**
40 * @var string
41 */
42 protected $cacheFileName;
43
44 /**
45 * @var \TYPO3\CMS\Core\Charset\CharsetConverter
46 */
47 protected $csConvObj;
48
49 /**
50 * @var string
51 */
52 protected $hashSource;
53
54 /**
55 * @var string
56 */
57 protected $sourceCharset;
58
59 /**
60 * @var string
61 */
62 protected $targetCharset;
63
64 /**
65 * Initializes the parser.
66 *
67 * @return void
68 */
69 public function __construct() {
70 $this->createCsConvObject();
71 }
72
73 /**
74 * Returns parsed representation of PHP locallang file.
75 *
76 * @param string $sourcePath Source file path
77 * @param string $languageKey Language key
78 * @param string $charset Charset
79 * @return array
80 * @throws \RuntimeException
81 */
82 public function getParsedData($sourcePath, $languageKey, $charset = '') {
83 $this->validateParameters($sourcePath, $languageKey);
84 $this->setCharsets($languageKey, $charset);
85 $this->generateCacheFileName($sourcePath, $languageKey);
86 if (!file_exists($this->cacheFileName)) {
87 $LOCAL_LANG = $this->generateCacheFile($sourcePath, $languageKey);
88 } else {
89 $LOCAL_LANG = $this->getContentFromCacheFile();
90 }
91 $xliff = $this->convertToXLIFF($LOCAL_LANG);
92 return $xliff;
93 }
94
95 /**
96 * Converts the LOCAL_LANG array to XLIFF structure.
97 *
98 * @param array $LOCAL_LANG
99 * @return array
100 */
101 protected function convertToXLIFF(array $LOCAL_LANG) {
102 foreach ($LOCAL_LANG as &$keysLabels) {
103 foreach ($keysLabels as &$label) {
104 $label = array(
105 0 => array(
106 'target' => $label
107 )
108 );
109 }
110 unset($label);
111 }
112 return $LOCAL_LANG;
113 }
114
115 /**
116 * Creates a character conversion object.
117 *
118 * @return void
119 */
120 protected function createCsConvObject() {
121 if (is_object($GLOBALS['LANG'])) {
122 $this->csConvObj = $GLOBALS['LANG']->csConvObj;
123 } elseif (is_object($GLOBALS['TSFE'])) {
124 $this->csConvObj = $GLOBALS['TSFE']->csConvObj;
125 } else {
126 $this->csConvObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Charset\\CharsetConverter');
127 }
128 }
129
130 /**
131 * Generates the cache file.
132 *
133 * @param string $sourcePath
134 * @param string $languageKey
135 * @return array
136 * @throws \RuntimeException
137 */
138 protected function generateCacheFile($sourcePath, $languageKey) {
139 $LOCAL_LANG = array();
140 // Get PHP data
141 include $sourcePath;
142 if (!is_array($LOCAL_LANG)) {
143 $fileName = substr($sourcePath, strlen(PATH_site));
144 throw new \RuntimeException(('TYPO3 Fatal Error: "' . $fileName) . '" is no TYPO3 language file!', 1308898491);
145 }
146 // Converting the default language (English)
147 // This needs to be done for a few accented loan words and extension names
148 if (is_array($LOCAL_LANG['default']) && $this->targetCharset !== 'utf-8') {
149 foreach ($LOCAL_LANG['default'] as &$labelValue) {
150 $labelValue = $this->csConvObj->conv($labelValue, 'utf-8', $this->targetCharset);
151 }
152 unset($labelValue);
153 }
154 if (($languageKey !== 'default' && is_array($LOCAL_LANG[$languageKey])) && $this->sourceCharset != $this->targetCharset) {
155 foreach ($LOCAL_LANG[$languageKey] as &$labelValue) {
156 $labelValue = $this->csConvObj->conv($labelValue, $this->sourceCharset, $this->targetCharset);
157 }
158 unset($labelValue);
159 }
160 // Cache the content now:
161 if (isset($LOCAL_LANG[$languageKey])) {
162 $serContent = array('origFile' => $this->hashSource, 'LOCAL_LANG' => array('default' => $LOCAL_LANG['default'], $languageKey => $LOCAL_LANG[$languageKey]));
163 } else {
164 $serContent = array('origFile' => $this->hashSource, 'LOCAL_LANG' => array('default' => $LOCAL_LANG['default']));
165 }
166 $res = \TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir($this->cacheFileName, serialize($serContent));
167 if ($res) {
168 throw new \RuntimeException('TYPO3 Fatal Error: "' . $res, 1308898501);
169 }
170 return $LOCAL_LANG;
171 }
172
173 /**
174 * Generates the name of the cached file.
175 *
176 * @param string $sourcePath
177 * @param string $languageKey
178 * @return void
179 */
180 protected function generateCacheFileName($sourcePath, $languageKey) {
181 $this->hashSource = ((substr($sourcePath, strlen(PATH_site)) . '|') . date('d-m-Y H:i:s', filemtime($sourcePath))) . '|version=2.3';
182 $this->cacheFileName = ((((((((PATH_site . 'typo3temp/llxml/') . substr(basename($sourcePath), 10, 15)) . '_') . \TYPO3\CMS\Core\Utility\GeneralUtility::shortMD5($this->hashSource)) . '.') . $languageKey) . '.') . $this->targetCharset) . '.cache';
183 }
184
185 /**
186 * Obtains the content from the cache file.
187 *
188 * @return array
189 */
190 protected function getContentFromCacheFile() {
191 $serContent = (array) unserialize(file_get_contents($this->cacheFileName));
192 $LOCAL_LANG = $serContent['LOCAL_LANG'];
193 return (array) $LOCAL_LANG;
194 }
195
196 /**
197 * Checks if the file is within the web root.
198 *
199 * @param string $fileName
200 * @return boolean
201 */
202 protected function isWithinWebRoot($fileName) {
203 return (bool) \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName($fileName);
204 }
205
206 /**
207 * Sets character sets for the language key.
208 *
209 * @param string $languageKey
210 * @param string $charset
211 * @return void
212 */
213 protected function setCharsets($languageKey, $charset) {
214 $this->sourceCharset = $this->csConvObj->parse_charset($this->csConvObj->charSetArray[$languageKey] ? $this->csConvObj->charSetArray[$languageKey] : 'utf-8');
215 if ($charset) {
216 $this->targetCharset = $this->csConvObj->parse_charset($charset);
217 } else {
218 $this->targetCharset = 'utf-8';
219 }
220 }
221
222 /**
223 * Validates parameters for the function.
224 *
225 * @param string $sourcePath
226 * @param string $languageKey
227 * @return void
228 * @throws \RuntimeException
229 */
230 protected function validateParameters($sourcePath, $languageKey) {
231 if ((!$this->isWithinWebRoot($sourcePath) || !@is_file($sourcePath)) || !$languageKey) {
232 throw new \RuntimeException(sprintf('Invalid source path (%s) or languageKey (%s)', $sourcePath, $languageKey), 1309245002);
233 }
234 }
235
236 }
237
238
239 ?>