‪TYPO3CMS  9.5
YamlFileLoader.php
Go to the documentation of this file.
1 <?php
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 
17 use Psr\Log\LoggerAwareInterface;
18 use Psr\Log\LoggerAwareTrait;
19 use Symfony\Component\Yaml\Yaml;
23 
40 class ‪YamlFileLoader implements LoggerAwareInterface
41 {
42  use LoggerAwareTrait;
43 
44  public const ‪PROCESS_PLACEHOLDERS = 1;
45  public const ‪PROCESS_IMPORTS = 2;
46 
54  public function ‪load(string $fileName, int $flags = self::PROCESS_PLACEHOLDERS | self::PROCESS_IMPORTS): array
55  {
56  $content = $this->‪getFileContents($fileName);
57  $content = Yaml::parse($content);
58 
59  if (!is_array($content)) {
60  throw new ‪YamlParseException(
61  'YAML file "' . $fileName . '" could not be parsed into valid syntax, probably empty?',
62  1497332874
63  );
64  }
65 
66  if (($flags & self::PROCESS_IMPORTS) === self::PROCESS_IMPORTS) {
67  $content = $this->‪processImports($content);
68  }
69  if (($flags & self::PROCESS_PLACEHOLDERS) === self::PROCESS_PLACEHOLDERS) {
70  // Check for "%" placeholders
71  $content = $this->‪processPlaceholders($content, $content);
72  }
73 
74  return $content;
75  }
76 
85  protected function ‪getFileContents(string $fileName): string
86  {
87  $streamlinedFileName = GeneralUtility::getFileAbsFileName($fileName);
88  if (!$streamlinedFileName) {
89  throw new ‪YamlFileLoadingException('YAML File "' . $fileName . '" could not be loaded', 1485784246);
90  }
91  return file_get_contents($streamlinedFileName);
92  }
93 
103  protected function ‪getValueFromEnv(string $value): string
104  {
105  $matches = [];
106  preg_match_all('/%env\‍([\'"]?(\w+)[\'"]?\‍)%/', $value, $matches);
107  $envVars = array_combine($matches[0], $matches[1]);
108  foreach ($envVars as $substring => $envVarName) {
109  $envVar = getenv($envVarName);
110  $value = $envVar ? str_replace($substring, $envVar, $value) : $value;
111  }
112  return $value;
113  }
114 
122  protected function ‪processImports(array $content): array
123  {
124  if (isset($content['imports']) && is_array($content['imports'])) {
125  foreach ($content['imports'] as $import) {
126  try {
127  $importedContent = $this->‪load($import['resource']);
128  // override the imported content with the one from the current file
129  $content = $this->‪merge($importedContent, $content);
130  } catch (‪YamlParseException | ‪YamlFileLoadingException $exception) {
131  $this->logger->error($exception->getMessage(), ['exception' => $exception]);
132  }
133  }
134  unset($content['imports']);
135  }
136  return $content;
137  }
138 
148  protected function ‪processPlaceholders(array $content, array $referenceArray): array
149  {
150  foreach ($content as $k => $v) {
151  if ($this->‪isEnvPlaceholder($v)) {
152  $content[$k] = $this->‪getValueFromEnv($v);
153  } elseif ($this->‪isPlaceholder($v)) {
154  $content[$k] = $this->‪getValueFromReferenceArray($v, $referenceArray);
155  } elseif (is_array($v)) {
156  $content[$k] = $this->‪processPlaceholders($v, $referenceArray);
157  }
158  }
159  return $content;
160  }
161 
170  protected function ‪getValueFromReferenceArray(string $placeholder, array $referenceArray)
171  {
172  $pointer = trim($placeholder, '%');
173  $parts = explode('.', $pointer);
174  $referenceData = $referenceArray;
175  foreach ($parts as $part) {
176  if (isset($referenceData[$part])) {
177  $referenceData = $referenceData[$part];
178  } else {
179  // return unsubstituted placeholder
180  return $placeholder;
181  }
182  }
183  if ($this->‪isPlaceholder($referenceData)) {
184  $referenceData = $this->‪getValueFromReferenceArray($referenceData, $referenceArray);
185  }
186  return $referenceData;
187  }
188 
195  protected function ‪isPlaceholder($value): bool
196  {
197  return is_string($value) && strpos($value, '%') === 0 && substr($value, -1) === '%';
198  }
199 
206  protected function ‪isEnvPlaceholder($value): bool
207  {
208  return is_string($value) && (strpos($value, '%env(') !== false);
209  }
210 
220  protected function ‪merge(array $val1, array $val2): array
221  {
222  // Simple lists get merged / added up
223  if (count(array_filter(array_keys($val1), 'is_int')) === count($val1)) {
224  return array_merge($val1, $val2);
225  }
226  foreach ($val1 as $k => $v) {
227  // The key also exists in second array, if it is a simple value
228  // then $val2 will override the value, where an array is calling merge() recursively.
229  if (isset($val2[$k])) {
230  if (is_array($v) && isset($val2[$k])) {
231  if (is_array($val2[$k])) {
232  $val1[$k] = $this->‪merge($v, $val2[$k]);
233  } else {
234  $val1[$k] = $val2[$k];
235  }
236  } else {
237  $val1[$k] = $val2[$k];
238  }
239  unset($val2[$k]);
240  }
241  }
242  // If there are properties in the second array left, they are added up
243  if (!empty($val2)) {
244  foreach ($val2 as $k => $v) {
245  $val1[$k] = $v;
246  }
247  }
248 
249  return $val1;
250  }
251 }
‪TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader\PROCESS_IMPORTS
‪const PROCESS_IMPORTS
Definition: YamlFileLoader.php:45
‪TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader\load
‪array load(string $fileName, int $flags=self::PROCESS_PLACEHOLDERS|self::PROCESS_IMPORTS)
Definition: YamlFileLoader.php:54
‪TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader\PROCESS_PLACEHOLDERS
‪const PROCESS_PLACEHOLDERS
Definition: YamlFileLoader.php:44
‪TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader\getValueFromReferenceArray
‪array mixed string getValueFromReferenceArray(string $placeholder, array $referenceArray)
Definition: YamlFileLoader.php:170
‪TYPO3\CMS\Core\Configuration\Loader\Exception\YamlParseException
Definition: YamlParseException.php:20
‪TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader\processPlaceholders
‪array processPlaceholders(array $content, array $referenceArray)
Definition: YamlFileLoader.php:148
‪TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader\isPlaceholder
‪bool isPlaceholder($value)
Definition: YamlFileLoader.php:195
‪TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader\merge
‪array merge(array $val1, array $val2)
Definition: YamlFileLoader.php:220
‪TYPO3\CMS\Core\Configuration\Loader\Exception\YamlFileLoadingException
Definition: YamlFileLoadingException.php:20
‪TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader\getValueFromEnv
‪string getValueFromEnv(string $value)
Definition: YamlFileLoader.php:103
‪TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader\isEnvPlaceholder
‪bool isEnvPlaceholder($value)
Definition: YamlFileLoader.php:206
‪TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader\getFileContents
‪string getFileContents(string $fileName)
Definition: YamlFileLoader.php:85
‪TYPO3\CMS\Core\Configuration\Loader
‪TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader
Definition: YamlFileLoader.php:41
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader\processImports
‪array processImports(array $content)
Definition: YamlFileLoader.php:122