9c7a53a1ecd09df4a26b44ee94b1071ef7c2c4e3
[Packages/TYPO3.CMS.git] / t3lib / l10n / parser / class.t3lib_l10n_parser_llxml.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 XML locallang file.
30 *
31 * @package TYPO3
32 * @subpackage t3lib
33 * @author Dominique Feyer <dfeyer@reelpeek.net>
34 */
35 class t3lib_l10n_parser_Llxml extends t3lib_l10n_parser_AbstractXml {
36
37 /**
38 * Associative array of "filename => parsed data" pairs.
39 *
40 * @var array
41 */
42 protected $parsedTargetFiles;
43
44 /**
45 * Returns parsed representation of XML file.
46 *
47 * @param string $sourcePath Source file path
48 * @param string $languageKey Language key
49 * @param string $charset Charset
50 * @return array
51 */
52 public function getParsedData($sourcePath, $languageKey, $charset = '') {
53 $this->sourcePath = $sourcePath;
54 $this->languageKey = $languageKey;
55 $this->charset = $this->getCharset($languageKey, $charset);
56
57 // Parse source
58 $parsedSource = $this->parseXmlFile();
59
60 // Parse target
61 $localizedTargetPath = t3lib_div::getFileAbsFileName(t3lib_div::llXmlAutoFileName($this->sourcePath, $this->languageKey));
62 $targetPath = ($this->languageKey !== 'default' && @is_file($localizedTargetPath)) ? $localizedTargetPath : $this->sourcePath;
63
64 try {
65 $parsedTarget = $this->getParsedTargetData($targetPath);
66 } catch (t3lib_l10n_exception_InvalidXmlFile $e) {
67 $parsedTarget = $this->getParsedTargetData($this->sourcePath);
68 }
69
70 $LOCAL_LANG = array();
71 $LOCAL_LANG[$languageKey] = t3lib_div::array_merge_recursive_overrule($parsedSource, $parsedTarget);
72
73 return $LOCAL_LANG;
74 }
75
76 /**
77 * Returns array representation of XLIFF data, starting from a root node.
78 *
79 * @param SimpleXMLElement $root XML root element
80 * @param string $element Target or Source
81 * @return array
82 */
83 protected function _doParsingFromRoot(SimpleXMLElement $root, $element) {
84 $bodyOfFileTag = $root->data->languageKey;
85
86 $parsedData = $this->_getParsedData($bodyOfFileTag, $element);
87
88 // Check if the source llxml file contains localized records
89 $localizedBodyOfFileTag = $root->data->xpath("languageKey[@index='" . $this->languageKey . "']");
90 if ($element === 'target' && isset($localizedBodyOfFileTag[0]) && $localizedBodyOfFileTag[0] instanceof SimpleXMLElement) {
91 $parsedData = array_merge($parsedData, $this->_getParsedData($localizedBodyOfFileTag[0], $element));
92 }
93
94 return $parsedData;
95 }
96
97 /**
98 * Parse the given language key tag
99 *
100 * @param SimpleXMLElement $bodyOfFileTag
101 * @param string $element
102 * @return array
103 */
104 protected function _getParsedData(SimpleXMLElement $bodyOfFileTag, $element) {
105 $parsedData = array();
106
107 if (count($bodyOfFileTag->children()) == 0) {
108 // Check for externally-referenced resource:
109 // <languageKey index="fr">EXT:yourext/path/to/localized/locallang.xml</languageKey>
110 $reference = sprintf('%s', $bodyOfFileTag);
111 if (substr($reference, -4) === '.xml') {
112 return $this->getParsedTargetData(t3lib_div::getFileAbsFileName($reference));
113 }
114 }
115 foreach ($bodyOfFileTag->children() as $translationElement) {
116 if ($translationElement->getName() === 'label') {
117 // If restype would be set, it could be metadata from Gettext to XLIFF conversion (and we don't need this data)
118 $parsedData[(string)$translationElement['index']][0] = array(
119 $element => (string)$translationElement,
120 );
121 }
122 }
123
124 return $parsedData;
125 }
126
127 /**
128 * Returns array representation of XLIFF data, starting from a root node.
129 *
130 * @param \SimpleXMLElement $root A root node
131 * @return array An array representing parsed XLIFF
132 */
133 protected function doParsingFromRoot(SimpleXMLElement $root) {
134 return $this->_doParsingFromRoot($root, 'source');
135 }
136
137 /**
138 * Returns array representation of XLIFF data, starting from a root node.
139 *
140 * @param \SimpleXMLElement $root A root node
141 * @return array An array representing parsed XLIFF
142 */
143 protected function doParsingTargetFromRoot(SimpleXMLElement $root) {
144 return $this->_doParsingFromRoot($root, 'target');
145 }
146
147 /**
148 * Returns parsed representation of XML file.
149 *
150 * Parses XML if it wasn't done before. Caches parsed data.
151 *
152 * @param string $path An absolute path to XML file
153 * @return array Parsed XML file
154 */
155 public function getParsedTargetData($path) {
156 if (!isset($this->parsedTargetFiles[$path])) {
157 $this->parsedTargetFiles[$path] = $this->parseXmlTargetFile($path);
158 }
159 return $this->parsedTargetFiles[$path];
160 }
161
162 /**
163 * Reads and parses XML file and returns internal representation of data.
164 *
165 * @throws t3lib_l10n_exception_InvalidXmlFile
166 * @param string $targetPath Path of the target file
167 * @return array
168 */
169 protected function parseXmlTargetFile($targetPath) {
170 $rootXmlNode = FALSE;
171
172 if (file_exists($targetPath)) {
173 $rootXmlNode = simplexml_load_file($targetPath, 'SimpleXmlElement', \LIBXML_NOWARNING);
174 }
175
176 if (!isset($rootXmlNode) || $rootXmlNode === FALSE) {
177 throw new t3lib_l10n_exception_InvalidXmlFile('The path provided does not point to existing and accessible well-formed XML file (' . $targetPath . ').', 1278155987);
178 }
179
180 return $this->doParsingTargetFromRoot($rootXmlNode);
181 }
182 }
183
184 ?>