TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
LocallangXmlParser.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Core\Localization\Parser;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
20 
25 {
31  protected $parsedTargetFiles;
32 
42  {
43  $this->sourcePath = $sourcePath;
44  $this->languageKey = $languageKey;
45  $this->charset = $this->getCharset($languageKey, $charset);
46  // Parse source
47  $parsedSource = $this->parseXmlFile();
48  // Parse target
49  $localizedTargetPath = GeneralUtility::getFileAbsFileName(GeneralUtility::llXmlAutoFileName($this->sourcePath, $this->languageKey));
50  $targetPath = $this->languageKey !== 'default' && @is_file($localizedTargetPath) ? $localizedTargetPath : $this->sourcePath;
51  try {
52  $parsedTarget = $this->getParsedTargetData($targetPath);
53  } catch (InvalidXmlFileException $e) {
54  $parsedTarget = $this->getParsedTargetData($this->sourcePath);
55  }
56  $LOCAL_LANG = [];
57  $LOCAL_LANG[$languageKey] = $parsedSource;
58  ArrayUtility::mergeRecursiveWithOverrule($LOCAL_LANG[$languageKey], $parsedTarget);
59  return $LOCAL_LANG;
60  }
61 
69  protected function doParsingFromRootForElement(\SimpleXMLElement $root, $element)
70  {
71  $bodyOfFileTag = $root->data->languageKey;
72  // Check if the source llxml file contains localized records
73  $localizedBodyOfFileTag = $root->data->xpath('languageKey[@index=\'' . $this->languageKey . '\']');
74  if ($element === 'source' || $this->languageKey === 'default') {
75  $parsedData = $this->getParsedDataForElement($bodyOfFileTag, $element);
76  } else {
77  $parsedData = [];
78  }
79  if ($element === 'target' && isset($localizedBodyOfFileTag[0]) && $localizedBodyOfFileTag[0] instanceof \SimpleXMLElement) {
80  $parsedDataTarget = $this->getParsedDataForElement($localizedBodyOfFileTag[0], $element);
81  $mergedData = $parsedDataTarget + $parsedData;
82  if ($this->languageKey === 'default') {
83  $parsedData = array_intersect_key($mergedData, $parsedData, $parsedDataTarget);
84  } else {
85  $parsedData = array_intersect_key($mergedData, $parsedDataTarget);
86  }
87  }
88  return $parsedData;
89  }
90 
98  protected function getParsedDataForElement(\SimpleXMLElement $bodyOfFileTag, $element)
99  {
100  $parsedData = [];
101  $children = $bodyOfFileTag->children();
102  if ($children->count() === 0) {
103  // Check for externally-referenced resource:
104  // <languageKey index="fr">EXT:yourext/path/to/localized/locallang.xml</languageKey>
105  $reference = sprintf('%s', $bodyOfFileTag);
106  if (substr($reference, -4) === '.xml') {
107  return $this->getParsedTargetData(GeneralUtility::getFileAbsFileName($reference));
108  }
109  }
111  foreach ($children as $translationElement) {
112  if ($translationElement->getName() === 'label') {
113  $parsedData[(string)$translationElement['index']][0] = [
114  $element => (string)$translationElement
115  ];
116  }
117  }
118  return $parsedData;
119  }
120 
127  protected function doParsingFromRoot(\SimpleXMLElement $root)
128  {
129  return $this->doParsingFromRootForElement($root, 'source');
130  }
131 
138  protected function doParsingTargetFromRoot(\SimpleXMLElement $root)
139  {
140  return $this->doParsingFromRootForElement($root, 'target');
141  }
142 
151  public function getParsedTargetData($path)
152  {
153  if (!isset($this->parsedTargetFiles[$path])) {
154  $this->parsedTargetFiles[$path] = $this->parseXmlTargetFile($path);
155  }
156  return $this->parsedTargetFiles[$path];
157  }
158 
166  protected function parseXmlTargetFile($targetPath)
167  {
168  $rootXmlNode = false;
169  if (file_exists($targetPath)) {
170  $xmlContent = file_get_contents($targetPath);
171  // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
172  $previousValueOfEntityLoader = libxml_disable_entity_loader(true);
173  $rootXmlNode = simplexml_load_string($xmlContent, 'SimpleXMLElement', LIBXML_NOWARNING);
174  libxml_disable_entity_loader($previousValueOfEntityLoader);
175  }
176  if (!isset($rootXmlNode) || $rootXmlNode === false) {
177  throw new InvalidXmlFileException('The path provided does not point to existing and accessible well-formed XML file (' . $targetPath . ').', 1278155987);
178  }
179  return $this->doParsingTargetFromRoot($rootXmlNode);
180  }
181 }
static llXmlAutoFileName($fileRef, $language, $sameLocation=false)
doParsingFromRootForElement(\SimpleXMLElement $root, $element)
getParsedData($sourcePath, $languageKey, $charset= '')
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
static getFileAbsFileName($filename, $_=null, $_2=null)