‪TYPO3CMS  10.4
LocallangXmlParser.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
22 
29 {
30  public function ‪__construct()
31  {
32  trigger_error(__CLASS__ . ' has been marked as deprecated and will be removed in TYPO3 v11. Consider using xlf files instead.', E_USER_DEPRECATED);
33  }
34 
40  protected ‪$parsedTargetFiles;
41 
50  {
51  $this->sourcePath = ‪$sourcePath;
52  $this->languageKey = ‪$languageKey;
53  // Parse source
54  $parsedSource = $this->‪parseXmlFile();
55  // Parse target
56  $localizedTargetPath = $this->‪getLocalizedFileName($this->sourcePath, $this->languageKey);
57  $targetPath = $this->languageKey !== 'default' && @is_file($localizedTargetPath) ? $localizedTargetPath : ‪$this->sourcePath;
58  try {
59  $parsedTarget = $this->‪getParsedTargetData($targetPath);
60  } catch (InvalidXmlFileException $e) {
61  $parsedTarget = $this->‪getParsedTargetData($this->sourcePath);
62  }
63  $LOCAL_LANG = [];
64  $LOCAL_LANG[‪$languageKey] = $parsedSource;
66  return $LOCAL_LANG;
67  }
68 
77  protected function ‪doParsingFromRootForElement(\SimpleXMLElement $root, $element)
78  {
79  $bodyOfFileTag = $root->data->languageKey;
80  if ($bodyOfFileTag === null) {
81  throw new InvalidXmlFileException('Invalid locallang.xml language file "' . ‪PathUtility::stripPathSitePrefix($this->sourcePath) . '"', 1487944884);
82  }
83 
84  if ($element === 'source' || $this->languageKey === 'default') {
85  $parsedData = $this->‪getParsedDataForElement($bodyOfFileTag, $element);
86  } else {
87  $parsedData = [];
88  }
89  if ($element === 'target') {
90  // Check if the source llxml file contains localized records
91  $localizedBodyOfFileTag = $root->data->xpath('languageKey[@index=\'' . $this->languageKey . '\']');
92  if (isset($localizedBodyOfFileTag[0]) && $localizedBodyOfFileTag[0] instanceof \SimpleXMLElement) {
93  $parsedDataTarget = $this->getParsedDataForElement($localizedBodyOfFileTag[0], $element);
94  $mergedData = $parsedDataTarget + $parsedData;
95  if ($this->languageKey === 'default') {
96  $parsedData = array_intersect_key($mergedData, $parsedData, $parsedDataTarget);
97  } else {
98  $parsedData = array_intersect_key($mergedData, $parsedDataTarget);
99  }
100  }
101  }
102  return $parsedData;
103  }
104 
112  protected function getParsedDataForElement(\SimpleXMLElement $bodyOfFileTag, $element)
113  {
114  $parsedData = [];
115  $children = $bodyOfFileTag->children();
116  if ($children->count() === 0) {
117  // Check for externally-referenced resource:
118  // <languageKey index="fr">EXT:yourext/path/to/localized/locallang.xml</languageKey>
119  $reference = sprintf('%s', $bodyOfFileTag);
120  if (substr($reference, -4) === '.xml') {
121  return $this->getParsedTargetData(GeneralUtility::getFileAbsFileName($reference));
122  }
123  }
125  foreach ($children as $translationElement) {
126  if ($translationElement->getName() === 'label') {
127  $parsedData[(string)$translationElement['index']][0] = [
128  $element => (string)$translationElement
129  ];
130  }
131  }
132  return $parsedData;
133  }
134 
141  protected function doParsingFromRoot(\SimpleXMLElement $root)
142  {
143  return $this->doParsingFromRootForElement($root, 'source');
144  }
145 
152  protected function doParsingTargetFromRoot(\SimpleXMLElement $root)
153  {
154  return $this->doParsingFromRootForElement($root, 'target');
155  }
156 
165  public function getParsedTargetData($path)
166  {
167  if (!isset($this->parsedTargetFiles[$path])) {
168  $this->parsedTargetFiles[$path] = $this->parseXmlTargetFile($path);
169  }
170  return $this->parsedTargetFiles[$path];
171  }
172 
180  protected function parseXmlTargetFile($targetPath)
181  {
182  $rootXmlNode = false;
183  if (file_exists($targetPath)) {
184  $xmlContent = file_get_contents($targetPath);
185  // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
186  $previousValueOfEntityLoader = null;
187  if (PHP_MAJOR_VERSION < 8) {
188  $previousValueOfEntityLoader = libxml_disable_entity_loader(true);
189  }
190  $rootXmlNode = simplexml_load_string($xmlContent, \SimpleXMLElement::class, LIBXML_NOWARNING);
191  if (PHP_MAJOR_VERSION < 8) {
192  libxml_disable_entity_loader($previousValueOfEntityLoader);
193  }
194  }
195  if ($rootXmlNode === false) {
196  $xmlError = libxml_get_last_error();
197  throw new InvalidXmlFileException(
198  'The path provided does not point to existing and accessible well-formed XML file. Reason: ' . $xmlError->message . ' in ' . $targetPath . ', line ' . $xmlError->line,
199  1278155987
200  );
201  }
202  return $this->doParsingTargetFromRoot($rootXmlNode);
203  }
204 }
‪TYPO3\CMS\Core\Localization\Parser\LocallangXmlParser\getParsedDataForElement
‪array getParsedDataForElement(\SimpleXMLElement $bodyOfFileTag, $element)
Definition: LocallangXmlParser.php:111
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:24
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:372
‪TYPO3\CMS\Core\Localization\Parser\LocallangXmlParser\doParsingFromRootForElement
‪array doParsingFromRootForElement(\SimpleXMLElement $root, $element)
Definition: LocallangXmlParser.php:76
‪TYPO3\CMS\Core\Localization\Parser\LocallangXmlParser\$parsedTargetFiles
‪array $parsedTargetFiles
Definition: LocallangXmlParser.php:39
‪TYPO3\CMS\Core\Localization\Parser\AbstractXmlParser\$sourcePath
‪string $sourcePath
Definition: AbstractXmlParser.php:32
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:654
‪TYPO3\CMS\Core\Localization\Parser\AbstractXmlParser
Definition: AbstractXmlParser.php:29
‪TYPO3\CMS\Core\Localization\Parser\LocallangXmlParser\getParsedData
‪array getParsedData($sourcePath, $languageKey)
Definition: LocallangXmlParser.php:48
‪TYPO3\CMS\Core\Localization\Parser\LocallangXmlParser\__construct
‪__construct()
Definition: LocallangXmlParser.php:30
‪TYPO3\CMS\Core\Localization\Parser\AbstractXmlParser\$languageKey
‪string $languageKey
Definition: AbstractXmlParser.php:36
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪TYPO3\CMS\Core\Localization\Parser
Definition: AbstractXmlParser.php:16
‪TYPO3\CMS\Core\Localization\Parser\AbstractXmlParser\parseXmlFile
‪array parseXmlFile()
Definition: AbstractXmlParser.php:71
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Localization\Exception\InvalidXmlFileException
Definition: InvalidXmlFileException.php:22
‪TYPO3\CMS\Core\Localization\Parser\AbstractXmlParser\getLocalizedFileName
‪string getLocalizedFileName($fileRef, $language, $sameLocation=false)
Definition: AbstractXmlParser.php:108
‪TYPO3\CMS\Core\Localization\Parser\LocallangXmlParser
Definition: LocallangXmlParser.php:29
‪TYPO3\CMS\Core\Localization\Parser\LocallangXmlParser\getParsedTargetData
‪array getParsedTargetData($path)
Definition: LocallangXmlParser.php:164