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