[CLEANUP] The correct case must be used for standard PHP types in phpdoc
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Resource / StorageRepository.php
1 <?php
2 namespace TYPO3\CMS\Core\Resource;
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 TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools;
18 use TYPO3\CMS\Core\Database\ConnectionPool;
19 use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
20 use TYPO3\CMS\Core\Log\LogManager;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22
23 /**
24 * Repository for accessing the file mounts
25 */
26 class StorageRepository extends AbstractRepository
27 {
28 /**
29 * @var NULL|array‚
30 */
31 protected static $storageRowCache = null;
32
33 /**
34 * @var string
35 */
36 protected $objectType = ResourceStorage::class;
37
38 /**
39 * @var string
40 */
41 protected $table = 'sys_file_storage';
42
43 /**
44 * @var string
45 */
46 protected $typeField = 'driver';
47
48 /**
49 * @var string
50 */
51 protected $driverField = 'driver';
52
53 /**
54 * @var \TYPO3\CMS\Core\Log\Logger
55 */
56 protected $logger;
57
58 public function __construct()
59 {
60 parent::__construct();
61
62 /** @var $logManager LogManager */
63 $logManager = GeneralUtility::makeInstance(LogManager::class);
64 $this->logger = $logManager->getLogger(__CLASS__);
65 }
66
67 /**
68 * @param int $uid
69 *
70 * @return null|ResourceStorage
71 */
72 public function findByUid($uid)
73 {
74 $this->initializeLocalCache();
75 if (isset(self::$storageRowCache[$uid])) {
76 return $this->factory->getStorageObject($uid, self::$storageRowCache[$uid]);
77 }
78 return null;
79 }
80
81 /**
82 * Initializes the Storage
83 */
84 protected function initializeLocalCache()
85 {
86 if (static::$storageRowCache === null) {
87 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
88 ->getQueryBuilderForTable($this->table);
89
90 if ($this->getEnvironmentMode() === 'FE' && !empty($GLOBALS['TSFE']->sys_page)) {
91 $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
92 }
93
94 $result = $queryBuilder
95 ->select('*')
96 ->from($this->table)
97 ->orderBy('name')
98 ->execute();
99
100 static::$storageRowCache = [];
101 while ($row = $result->fetch()) {
102 if (!empty($row['uid'])) {
103 static::$storageRowCache[$row['uid']] = $row;
104 }
105 }
106
107 // if no storage is created before or the user has not access to a storage
108 // static::$storageRowCache would have the value array()
109 // so check if there is any record. If no record is found, create the fileadmin/ storage
110 // selecting just one row is enough
111
112 if (static::$storageRowCache === []) {
113 $connection = GeneralUtility::makeInstance(ConnectionPool::class)
114 ->getConnectionForTable($this->table);
115
116 $storageObjectsCount = $connection->count('uid', $this->table, []);
117
118 if ($storageObjectsCount === 0) {
119 if ($this->createLocalStorage(
120 'fileadmin/ (auto-created)',
121 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'],
122 'relative',
123 'This is the local fileadmin/ directory. This storage mount has been created automatically by TYPO3.',
124 true
125 ) > 0) {
126 // reset to null to force reloading of storages
127 static::$storageRowCache = null;
128 // call self for initialize Cache
129 $this->initializeLocalCache();
130 }
131 }
132 }
133 }
134 }
135
136 /**
137 * Finds storages by type, i.e. the driver used
138 *
139 * @param string $storageType
140 * @return ResourceStorage[]
141 */
142 public function findByStorageType($storageType)
143 {
144 $this->initializeLocalCache();
145
146 /** @var $driverRegistry Driver\DriverRegistry */
147 $driverRegistry = GeneralUtility::makeInstance(Driver\DriverRegistry::class);
148
149 $storageObjects = [];
150 foreach (static::$storageRowCache as $storageRow) {
151 if ($storageRow['driver'] !== $storageType) {
152 continue;
153 }
154 if ($driverRegistry->driverExists($storageRow['driver'])) {
155 $storageObjects[] = $this->factory->getStorageObject($storageRow['uid'], $storageRow);
156 } else {
157 $this->logger->warning(
158 sprintf('Could not instantiate storage "%s" because of missing driver.', [$storageRow['name']]),
159 $storageRow
160 );
161 }
162 }
163 return $storageObjects;
164 }
165
166 /**
167 * Returns a list of mountpoints that are available in the VFS.
168 * In case no storage exists this automatically created a storage for fileadmin/
169 *
170 * @return ResourceStorage[]
171 */
172 public function findAll()
173 {
174 $this->initializeLocalCache();
175
176 /** @var $driverRegistry Driver\DriverRegistry */
177 $driverRegistry = GeneralUtility::makeInstance(Driver\DriverRegistry::class);
178
179 $storageObjects = [];
180 foreach (static::$storageRowCache as $storageRow) {
181 if ($driverRegistry->driverExists($storageRow['driver'])) {
182 $storageObjects[] = $this->factory->getStorageObject($storageRow['uid'], $storageRow);
183 } else {
184 $this->logger->warning(
185 sprintf('Could not instantiate storage "%s" because of missing driver.', [$storageRow['name']]),
186 $storageRow
187 );
188 }
189 }
190 return $storageObjects;
191 }
192
193 /**
194 * Create the initial local storage base e.g. for the fileadmin/ directory.
195 *
196 * @param string $name
197 * @param string $basePath
198 * @param string $pathType
199 * @param string $description
200 * @param bool $default set to default storage
201 * @return int uid of the inserted record
202 */
203 public function createLocalStorage($name, $basePath, $pathType, $description = '', $default = false)
204 {
205 $caseSensitive = $this->testCaseSensitivity($pathType === 'relative' ? PATH_site . $basePath : $basePath);
206 // create the FlexForm for the driver configuration
207 $flexFormData = [
208 'data' => [
209 'sDEF' => [
210 'lDEF' => [
211 'basePath' => ['vDEF' => rtrim($basePath, '/') . '/'],
212 'pathType' => ['vDEF' => $pathType],
213 'caseSensitive' => ['vDEF' => $caseSensitive]
214 ]
215 ]
216 ]
217 ];
218
219 /** @var $flexObj FlexFormTools */
220 $flexObj = GeneralUtility::makeInstance(FlexFormTools::class);
221 $flexFormXml = $flexObj->flexArray2Xml($flexFormData, true);
222
223 // create the record
224 $field_values = [
225 'pid' => 0,
226 'tstamp' => $GLOBALS['EXEC_TIME'],
227 'crdate' => $GLOBALS['EXEC_TIME'],
228 'name' => $name,
229 'description' => $description,
230 'driver' => 'Local',
231 'configuration' => $flexFormXml,
232 'is_online' => 1,
233 'is_browsable' => 1,
234 'is_public' => 1,
235 'is_writable' => 1,
236 'is_default' => $default ? 1 : 0
237 ];
238
239 $dbConnection = GeneralUtility::makeInstance(ConnectionPool::class)
240 ->getConnectionForTable($this->table);
241 $dbConnection->insert($this->table, $field_values);
242
243 return (int)$dbConnection->lastInsertId($this->table);
244 }
245
246 /**
247 * Creates an object managed by this repository.
248 *
249 * @param array $databaseRow
250 * @return ResourceStorage
251 */
252 protected function createDomainObject(array $databaseRow)
253 {
254 return $this->factory->getStorageObject($databaseRow['uid'], $databaseRow);
255 }
256
257 /**
258 * Test if the local filesystem is case sensitive
259 *
260 * @param string $absolutePath
261 * @return bool
262 */
263 protected function testCaseSensitivity($absolutePath)
264 {
265 $caseSensitive = true;
266 $path = rtrim($absolutePath, '/') . '/aAbB';
267 $testFileExists = @file_exists($path);
268
269 // create test file
270 if (!$testFileExists) {
271 touch($path);
272 }
273
274 // do the actual sensitivity check
275 if (@file_exists(strtoupper($path)) && @file_exists(strtolower($path))) {
276 $caseSensitive = false;
277 }
278
279 // clean filesystem
280 if (!$testFileExists) {
281 unlink($path);
282 }
283
284 return $caseSensitive;
285 }
286 }