[TASK] Merge linkvalidator for beta2
[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 foreach ($bodyOfFileTag->children() as $translationElement) {
108 if ($translationElement->getName() === 'label') {
109 // If restype would be set, it could be metadata from Gettext to XLIFF conversion (and we don't need this data)
110 $parsedData[(string)$translationElement['index']][0] = array(
111 $element => (string)$translationElement,
112 );
113 }
114 }
115
116 return $parsedData;
117 }
118
119 /**
120 * Returns array representation of XLIFF data, starting from a root node.
121 *
122 * @param \SimpleXMLElement $root A root node
123 * @return array An array representing parsed XLIFF
124 */
125 protected function doParsingFromRoot(SimpleXMLElement $root) {
126 return $this->_doParsingFromRoot($root, 'source');
127 }
128
129 /**
130 * Returns array representation of XLIFF data, starting from a root node.
131 *
132 * @param \SimpleXMLElement $root A root node
133 * @return array An array representing parsed XLIFF
134 */
135 protected function doParsingTargetFromRoot(SimpleXMLElement $root) {
136 return $this->_doParsingFromRoot($root, 'target');
137 }
138
139 /**
140 * Returns parsed representation of XML file.
141 *
142 * Parses XML if it wasn't done before. Caches parsed data.
143 *
144 * @param string $path An absolute path to XML file
145 * @return array Parsed XML file
146 */
147 public function getParsedTargetData($path) {
148 if (!isset($this->parsedTargetFiles[$path])) {
149 $this->parsedTargetFiles[$path] = $this->parseXmlTargetFile($path);
150 }
151 return $this->parsedTargetFiles[$path];
152 }
153
154 /**
155 * Reads and parses XML file and returns internal representation of data.
156 *
157 * @throws t3lib_l10n_exception_InvalidXmlFile
158 * @param string $targetPath Path of the target file
159 * @return array
160 */
161 protected function parseXmlTargetFile($targetPath) {
162 $rootXmlNode = FALSE;
163
164 if (file_exists($targetPath)) {
165 $rootXmlNode = simplexml_load_file($targetPath, 'SimpleXmlElement', \LIBXML_NOWARNING);
166 }
167
168 if (!isset($rootXmlNode) || $rootXmlNode === FALSE) {
169 throw new t3lib_l10n_exception_InvalidXmlFile('The path provided does not point to existing and accessible well-formed XML file (' . $targetPath . ').', 1278155987);
170 }
171
172 return $this->doParsingTargetFromRoot($rootXmlNode);
173 }
174 }
175
176 ?>