[TASK] Remove superfluous indention level in site configuration yaml
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Configuration / SiteConfiguration.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Core\Configuration;
5
6 /*
7 * This file is part of the TYPO3 CMS project.
8 *
9 * It is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License, either version 2
11 * of the License, or any later version.
12 *
13 * For the full copyright and license information, please read the
14 * LICENSE.txt file that was distributed with this source code.
15 *
16 * The TYPO3 project - inspiring people to share!
17 */
18
19 use Symfony\Component\Finder\Finder;
20 use Symfony\Component\Yaml\Yaml;
21 use TYPO3\CMS\Core\Cache\CacheManager;
22 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
23 use TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader;
24 use TYPO3\CMS\Core\Exception\SiteNotFoundException;
25 use TYPO3\CMS\Core\Site\Entity\Site;
26 use TYPO3\CMS\Core\Utility\GeneralUtility;
27
28 /**
29 * Responsibility: Handles the format of the configuration (currently yaml), and the location of the file system folder
30 *
31 * Reads all available site configuration options, and puts them into Site objects.
32 *
33 * @internal
34 */
35 class SiteConfiguration
36 {
37 /**
38 * @var string
39 */
40 protected $configPath;
41
42 /**
43 * Config yaml file name.
44 *
45 * @internal
46 * @var string
47 */
48 protected $configFileName = 'config.yaml';
49
50 /**
51 * Identifier to store all configuration data in cache_core cache.
52 *
53 * @internal
54 * @var string
55 */
56 protected $cacheIdentifier = 'site-configuration';
57
58 /**
59 * @param string $configPath
60 */
61 public function __construct(string $configPath)
62 {
63 $this->configPath = $configPath;
64 }
65
66 /**
67 * Return all site objects which have been found in the filesystem.
68 *
69 * @return Site[]
70 */
71 public function resolveAllExistingSites(): array
72 {
73 $sites = [];
74 $siteConfiguration = $this->getAllSiteConfigurationFromFiles();
75 foreach ($siteConfiguration as $identifier => $configuration) {
76 $rootPageId = (int)($configuration['rootPageId'] ?? 0);
77 if ($rootPageId > 0) {
78 $sites[$identifier] = GeneralUtility::makeInstance(Site::class, $identifier, $rootPageId, $configuration);
79 }
80 }
81 return $sites;
82 }
83
84 /**
85 * Read the site configuration from config files.
86 *
87 * @return array
88 * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
89 */
90 protected function getAllSiteConfigurationFromFiles(): array
91 {
92 // Check if the data is already cached
93 if ($siteConfiguration = $this->getCache()->get($this->cacheIdentifier)) {
94 $siteConfiguration = json_decode($siteConfiguration, true);
95 }
96
97 // Nothing in the cache (or no site found)
98 if (empty($siteConfiguration)) {
99 $finder = new Finder();
100 try {
101 $finder->files()->depth(0)->name($this->configFileName)->in($this->configPath . '/*');
102 } catch (\InvalidArgumentException $e) {
103 // Directory $this->configPath does not exist yet
104 $finder = [];
105 }
106 $loader = GeneralUtility::makeInstance(YamlFileLoader::class);
107 $siteConfiguration = [];
108 foreach ($finder as $fileInfo) {
109 $configuration = $loader->load(GeneralUtility::fixWindowsFilePath((string)$fileInfo));
110 $identifier = basename($fileInfo->getPath());
111 if (isset($configuration['site'])) {
112 trigger_error(
113 'Site configuration with key \'site\' has been deprecated, remove indentation level and site key.',
114 E_USER_DEPRECATED
115 );
116 $configuration = $configuration['site'];
117 }
118 $siteConfiguration[$identifier] = $configuration;
119 }
120 $this->getCache()->set($this->cacheIdentifier, json_encode($siteConfiguration));
121 }
122 return $siteConfiguration ?? [];
123 }
124
125 /**
126 * Add or update a site configuration
127 *
128 * @param string $siteIdentifier
129 * @param array $configuration
130 * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
131 */
132 public function write(string $siteIdentifier, array $configuration): void
133 {
134 $fileName = $this->configPath . '/' . $siteIdentifier . '/' . $this->configFileName;
135 if (!file_exists($fileName)) {
136 GeneralUtility::mkdir_deep($this->configPath . '/' . $siteIdentifier);
137 }
138 $yamlFileContents = Yaml::dump($configuration, 99, 2);
139 GeneralUtility::writeFile($fileName, $yamlFileContents);
140 $this->getCache()->remove($this->cacheIdentifier);
141 }
142
143 /**
144 * Renames a site identifier (and moves the folder)
145 *
146 * @param string $currentIdentifier
147 * @param string $newIdentifier
148 * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
149 */
150 public function rename(string $currentIdentifier, string $newIdentifier): void
151 {
152 $result = rename($this->configPath . '/' . $currentIdentifier, $this->configPath . '/' . $newIdentifier);
153 if (!$result) {
154 throw new \RuntimeException('Unable to rename folder sites/' . $currentIdentifier, 1522491300);
155 }
156 $this->getCache()->remove($this->cacheIdentifier);
157 }
158
159 /**
160 * Removes the config.yaml file of a site configuration.
161 * Also clears the cache.
162 *
163 * @param string $siteIdentifier
164 * @throws SiteNotFoundException
165 */
166 public function delete(string $siteIdentifier): void
167 {
168 $sites = $this->resolveAllExistingSites();
169 if (!isset($sites[$siteIdentifier])) {
170 throw new SiteNotFoundException('Site configuration named ' . $siteIdentifier . ' not found.', 1522866183);
171 }
172 $fileName = $this->configPath . '/' . $siteIdentifier . '/' . $this->configFileName;
173 if (!file_exists($fileName)) {
174 throw new SiteNotFoundException('Site configuration file ' . $this->configFileName . ' within the site ' . $siteIdentifier . ' not found.', 1522866184);
175 }
176 @unlink($fileName);
177 $this->getCache()->remove($this->cacheIdentifier);
178 }
179
180 /**
181 * Short-hand function for the cache
182 *
183 * @return FrontendInterface
184 * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
185 */
186 protected function getCache(): FrontendInterface
187 {
188 return GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_core');
189 }
190 }