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