[TASK] Fix old classnames in extensionmanager
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Classes / Utility / Repository / Helper.php
1 <?php
2 namespace TYPO3\CMS\Extensionmanager\Utility\Repository;
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\Extensionmanager\Exception\ExtensionManagerException;
18 use TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility;
19
20 /**
21 * Central utility class for repository handling.
22 */
23 class Helper implements \TYPO3\CMS\Core\SingletonInterface
24 {
25 /**
26 * ##########################################
27 * Problem constants - to be used in bitmasks
28 * ##########################################
29 */
30 /**
31 * Type of problem: extension file not existing in file system.
32 *
33 * @var int
34 */
35 const PROBLEM_EXTENSION_FILE_NOT_EXISTING = 1;
36 /**
37 * Type of problem: wrong hash indicates outdated extension file.
38 *
39 * @var int
40 */
41 const PROBLEM_EXTENSION_HASH_CHANGED = 2;
42 /**
43 * Type of problem: no version records in database.
44 *
45 * @var int
46 */
47 const PROBLEM_NO_VERSIONS_IN_DATABASE = 4;
48 /**
49 * Keeps instance of repository class.
50 *
51 * @var \TYPO3\CMS\Extensionmanager\Domain\Model\Repository
52 */
53 protected $repository = null;
54
55 /**
56 * @var \TYPO3\CMS\Extensionmanager\Domain\Repository\RepositoryRepository
57 */
58 protected $repositoryRepository;
59
60 /**
61 * @var \TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository
62 */
63 protected $extensionRepository;
64
65 /**
66 * @var \TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility
67 */
68 protected $configurationUtility;
69
70 /**
71 * Class constructor.
72 *
73 * @access public
74 */
75 public function __construct()
76 {
77 /** @var $objectManager \TYPO3\CMS\Extbase\Object\ObjectManager */
78 $this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
79 /** @var \TYPO3\CMS\Extensionmanager\Domain\Repository\RepositoryRepository $repositoryRepository */
80 $repositoryRepository = $this->objectManager->get(\TYPO3\CMS\Extensionmanager\Domain\Repository\RepositoryRepository::class);
81 $this->extensionRepository = $this->objectManager->get(\TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository::class);
82 $this->configurationUtility = $this->objectManager->get(ConfigurationUtility::class);
83 /** @var \TYPO3\CMS\Extensionmanager\Domain\Model\Repository $repository */
84 $repository = $repositoryRepository->findByUid(1);
85 if (is_object($repository)) {
86 $this->setRepository($repository);
87 }
88 }
89
90 /**
91 * Method registers required repository instance to work with.
92 *
93 * Repository instance is passed by reference.
94 *
95 * @access public
96 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Repository $repository
97 * @return void
98 * @see $repository
99 */
100 public function setRepository(\TYPO3\CMS\Extensionmanager\Domain\Model\Repository $repository)
101 {
102 $this->repository = $repository;
103 }
104
105 /**
106 * Method fetches extension list file from remote server.
107 *
108 * Delegates to {@link fetchFile()}.
109 *
110 * @access public
111 * @return void
112 * @throws ExtensionManagerException
113 * @see fetchFile()
114 */
115 public function fetchExtListFile()
116 {
117 $this->fetchFile($this->getRemoteExtListFile(), $this->getLocalExtListFile());
118 }
119
120 /**
121 * Method fetches mirror list file from remote server.
122 *
123 * Delegates to {@link fetchFile()}.
124 *
125 * @access public
126 * @return void
127 * @throws ExtensionManagerException
128 * @see fetchFile()
129 */
130 public function fetchMirrorListFile()
131 {
132 $this->fetchFile($this->getRemoteMirrorListFile(), $this->getLocalMirrorListFile());
133 }
134
135 /**
136 * Method fetches contents from remote server and
137 * writes them into a file in the local file system.
138 *
139 * @param string $remoteResource remote resource to read contents from
140 * @param string $localResource local resource (absolute file path) to store retrieved contents to (must be within typo3temp/)
141 * @return void
142 * @see \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl(), \TYPO3\CMS\Core\Utility\GeneralUtility::writeFile()
143 * @throws ExtensionManagerException
144 */
145 protected function fetchFile($remoteResource, $localResource)
146 {
147 if ($this->configurationUtility->getCurrentConfiguration('extensionmanager')['offlineMode']['value']) {
148 throw new ExtensionManagerException('Extension Manager is in offline mode. No TER connection available.', 1437078780);
149 }
150 if (is_string($remoteResource) && is_string($localResource) && !empty($remoteResource) && !empty($localResource)) {
151 $fileContent = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($remoteResource, 0, array(TYPO3_user_agent));
152 if ($fileContent !== false) {
153 if (\TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir($localResource, $fileContent) !== null) {
154 throw new ExtensionManagerException(sprintf('Could not write to file %s.', $localResource), 1342635378);
155 }
156 } else {
157 throw new ExtensionManagerException(sprintf('Could not access remote resource %s.', $remoteResource), 1342635425);
158 }
159 }
160 }
161
162 /**
163 * Method returns location of local extension list file.
164 *
165 * @access public
166 * @return string local location of file
167 * @see getRemoteExtListFile()
168 */
169 public function getLocalExtListFile()
170 {
171 return PATH_site . 'typo3temp/var/ExtensionManager/' . (int)$this->repository->getUid() . '.extensions.xml.gz';
172 }
173
174 /**
175 * Method returns location of remote extension list file.
176 *
177 * @access public
178 * @return string remote location of file
179 * @see getLocalExtListFile()
180 */
181 public function getRemoteExtListFile()
182 {
183 $mirror = $this->getMirrors(true)->getMirror();
184 $filePath = 'https://' . $mirror['host'] . $mirror['path'] . 'extensions.xml.gz';
185 return $filePath;
186 }
187
188 /**
189 * Method returns location of remote file containing
190 * the extension checksum hash.
191 *
192 * @access public
193 * @return string remote location of file
194 */
195 public function getRemoteExtHashFile()
196 {
197 $mirror = $this->getMirrors(true)->getMirror();
198 $filePath = 'https://' . $mirror['host'] . $mirror['path'] . 'extensions.md5';
199 return $filePath;
200 }
201
202 /**
203 * Method returns location of local mirror list file.
204 *
205 * @access public
206 * @return string local location of file
207 * @see getRemoteMirrorListFile()
208 */
209 public function getLocalMirrorListFile()
210 {
211 return PATH_site . 'typo3temp/var/ExtensionManager/' . (int)$this->repository->getUid() . '.mirrors.xml.gz';
212 }
213
214 /**
215 * Method returns location of remote mirror list file.
216 *
217 * @access public
218 * @return string remote location of file
219 * @see getLocalMirrorListFile()
220 */
221 public function getRemoteMirrorListFile()
222 {
223 $filePath = $this->repository->getMirrorListUrl();
224 return $filePath;
225 }
226
227 /**
228 * Method returns available mirrors for registered repository.
229 *
230 * If there are no mirrors registered to the repository,
231 * the method will retrieve them from file system or remote
232 * server.
233 *
234 * @access public
235 * @param bool $forcedUpdateFromRemote if boolean TRUE, mirror configuration will always retrieved from remote server
236 * @return \TYPO3\CMS\Extensionmanager\Domain\Model\Mirrors instance of repository mirrors class
237 * @throws ExtensionManagerException
238 */
239 public function getMirrors($forcedUpdateFromRemote = true)
240 {
241 $assignedMirror = $this->repository->getMirrors();
242 if ($forcedUpdateFromRemote || is_null($assignedMirror) || !is_object($assignedMirror)) {
243 if ($forcedUpdateFromRemote || !is_file($this->getLocalMirrorListFile())) {
244 $this->fetchMirrorListFile();
245 }
246 /** @var $objMirrorListImporter \TYPO3\CMS\Extensionmanager\Utility\Importer\MirrorListUtility */
247 $objMirrorListImporter = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extensionmanager\Utility\Importer\MirrorListUtility::class);
248 $this->repository->addMirrors($objMirrorListImporter->getMirrors($this->getLocalMirrorListFile()));
249 }
250 return $this->repository->getMirrors();
251 }
252
253 /**
254 * Method returns information if currently available
255 * extension list might be outdated.
256 *
257 * @access public
258 * @see \TYPO3\CMS\Extensionmanager\Utility\Repository\Helper::PROBLEM_NO_VERSIONS_IN_DATABASE,
259 * @throws ExtensionManagerException
260 * @return int "0" if everything is perfect, otherwise bitmask with problems
261 */
262 public function isExtListUpdateNecessary()
263 {
264 $updateNecessity = 0;
265 if ($this->extensionRepository->countByRepository($this->repository->getUid()) <= 0) {
266 $updateNecessity |= self::PROBLEM_NO_VERSIONS_IN_DATABASE;
267 }
268 if (!is_file($this->getLocalExtListFile())) {
269 $updateNecessity |= self::PROBLEM_EXTENSION_FILE_NOT_EXISTING;
270 } else {
271 $remotemd5 = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($this->getRemoteExtHashFile(), 0, array(TYPO3_user_agent));
272 if ($remotemd5 !== false) {
273 $localmd5 = md5_file($this->getLocalExtListFile());
274 if ($remotemd5 !== $localmd5) {
275 $updateNecessity |= self::PROBLEM_EXTENSION_HASH_CHANGED;
276 }
277 } else {
278 throw new ExtensionManagerException('Could not retrieve extension hash file from remote server.', 1342635016);
279 }
280 }
281 return $updateNecessity;
282 }
283
284 /**
285 * Method updates TYPO3 database with up-to-date
286 * extension version records.
287 *
288 * @return bool TRUE if the extension list was successfully update, FALSE if no update necessary
289 * @throws ExtensionManagerException
290 * @see isExtListUpdateNecessary()
291 */
292 public function updateExtList()
293 {
294 $updated = false;
295 $updateNecessity = $this->isExtListUpdateNecessary();
296 if ($updateNecessity !== 0) {
297 // retrieval of file necessary
298 $tmpBitmask = self::PROBLEM_EXTENSION_FILE_NOT_EXISTING | self::PROBLEM_EXTENSION_HASH_CHANGED;
299 if (($tmpBitmask & $updateNecessity) > 0) {
300 $this->fetchExtListFile();
301 $updateNecessity &= ~$tmpBitmask;
302 }
303 // database table cleanup
304 if ($updateNecessity & self::PROBLEM_NO_VERSIONS_IN_DATABASE) {
305 $updateNecessity &= ~self::PROBLEM_NO_VERSIONS_IN_DATABASE;
306 } else {
307 // Use straight query as extbase "remove" is too slow here
308 // This truncates the whole table. It would be more correct to remove only rows of a specific
309 // repository, but multiple repository handling is not implemented, and truncate is quicker.
310 $this->getDatabaseConnection()->exec_TRUNCATEquery('tx_extensionmanager_domain_model_extension');
311 }
312 // no further problems - start of import process
313 if ($updateNecessity === 0) {
314 $uid = $this->repository->getUid();
315 /* @var $objExtListImporter \TYPO3\CMS\Extensionmanager\Utility\Importer\ExtensionListUtility */
316 $objExtListImporter = $this->objectManager->get(\TYPO3\CMS\Extensionmanager\Utility\Importer\ExtensionListUtility::class);
317 $objExtListImporter->import($this->getLocalExtListFile(), $uid);
318 $updated = true;
319 }
320 }
321 return $updated;
322 }
323
324 /**
325 * Get database connection
326 *
327 * @return \TYPO3\CMS\Core\Database\DatabaseConnection
328 */
329 protected function getDatabaseConnection()
330 {
331 return $GLOBALS['TYPO3_DB'];
332 }
333 }