[!!!][TASK] Remove mediace from the Core
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Updates / AbstractDownloadExtensionUpdate.php
1 <?php
2 namespace TYPO3\CMS\Install\Updates;
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\Package\PackageManager;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19 use TYPO3\CMS\Extbase\Object\ObjectManager;
20 use TYPO3\CMS\Extensionmanager\Utility\Connection\TerUtility;
21 use TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility;
22 use TYPO3\CMS\Extensionmanager\Utility\InstallUtility;
23 use TYPO3\CMS\Extensionmanager\Utility\ListUtility;
24
25 /**
26 * Download extension from TER
27 */
28 abstract class AbstractDownloadExtensionUpdate extends AbstractUpdate
29 {
30
31 /**
32 * @var string
33 */
34 protected $title = 'Install an Extension from the Extension Repository';
35
36 /**
37 * See subclasses for more information
38 * @var array
39 */
40 protected $extensionDetails = [];
41
42 /**
43 * @var string
44 */
45 protected $repositoryUrl = 'https://typo3.org/fileadmin/ter/@filename';
46
47 /**
48 * This method can be called to install an extension following all proper processes
49 * (e.g. installing in extList, respecting priority, etc.)
50 *
51 * @param string $extensionKey
52 * @param mixed $customMessages
53 * @return bool whether the installation worked or not
54 */
55 protected function installExtension($extensionKey, &$customMessages)
56 {
57 $updateSuccessful = true;
58 /** @var $objectManager ObjectManager */
59 $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
60
61 /** @var $extensionListUtility ListUtility */
62 $extensionListUtility = $objectManager->get(ListUtility::class);
63
64 $availableExtensions = $extensionListUtility->getAvailableExtensions();
65 $availableAndInstalledExtensions = $extensionListUtility->getAvailableAndInstalledExtensions($availableExtensions);
66
67 // Extension is not downloaded yet.
68 if (!is_array($availableAndInstalledExtensions[$extensionKey])) {
69 /** @var $extensionTerUtility TerUtility */
70 $extensionTerUtility = $objectManager->get(TerUtility::class);
71 $extensionDetails = $this->getExtensionDetails($extensionKey);
72 if (empty($extensionDetails)) {
73 $updateSuccessful = false;
74 $customMessages .= 'No version information for extension ' . $extensionKey . ' found. Can not install the extension.';
75 }
76 $t3xContent = $this->fetchExtension($extensionKey, $extensionDetails['versionString']);
77 if (empty($t3xContent)) {
78 $updateSuccessful = false;
79 $customMessages .= 'The extension ' . $extensionKey . ' could not be downloaded.';
80 }
81 $t3xExtracted = $extensionTerUtility->decodeExchangeData($t3xContent);
82 if (empty($t3xExtracted) || !is_array($t3xExtracted) || empty($t3xExtracted['extKey'])) {
83 $updateSuccessful = false;
84 $customMessages .= 'The extension ' . $extensionKey . ' could not be extracted.';
85 }
86
87 /** @var $extensionFileHandlingUtility FileHandlingUtility */
88 $extensionFileHandlingUtility = $objectManager->get(FileHandlingUtility::class);
89 $extensionFileHandlingUtility->unpackExtensionFromExtensionDataArray($t3xExtracted);
90
91 // the list utility now needs to have the regenerated list of packages
92 /** @var PackageManager $packageManager */
93 $packageManager = $objectManager->get(PackageManager::class);
94 $packageManager->scanAvailablePackages();
95 $extensionListUtility->reloadAvailableExtensions();
96 }
97
98 if ($updateSuccessful !== false) {
99 /** @var $extensionInstallUtility InstallUtility */
100 $extensionInstallUtility = $objectManager->get(InstallUtility::class);
101 $extensionInstallUtility->install($extensionKey);
102 }
103 return $updateSuccessful;
104 }
105
106 /**
107 * Returns the details of a local or external extension
108 *
109 * @param string $extensionKey Key of the extension to check
110 *
111 * @return array Extension details
112 */
113 protected function getExtensionDetails($extensionKey)
114 {
115 if (array_key_exists($extensionKey, $this->extensionDetails)) {
116 return $this->extensionDetails[$extensionKey];
117 }
118
119 return [];
120 }
121
122 /**
123 * Fetch extension from repository
124 *
125 * @param string $extensionKey The extension key to fetch
126 * @param string $version The version to fetch
127 *
128 * @throws \InvalidArgumentException
129 * @return string T3X file content
130 */
131 protected function fetchExtension($extensionKey, $version)
132 {
133 if (empty($extensionKey) || empty($version)) {
134 throw new \InvalidArgumentException('No extension key for fetching an extension was given.',
135 1344687432);
136 }
137
138 $filename = $extensionKey[0] . '/' . $extensionKey[1] . '/' . $extensionKey . '_' . $version . '.t3x';
139 $url = str_replace('@filename', $filename, $this->repositoryUrl);
140
141 return $this->fetchUrl($url);
142 }
143
144 /**
145 * Open an URL and return the response
146 *
147 * This wrapper method is required to try several download methods if
148 * the configuration is not valid or initially written by the installer.
149 *
150 * @param string $url The URL to file
151 *
152 * @throws \Exception
153 * @throws \InvalidArgumentException
154 * @return string File content
155 */
156 protected function fetchUrl($url)
157 {
158 if (empty($url)) {
159 throw new \InvalidArgumentException('No URL for downloading an extension given.',
160 1344687436);
161 }
162
163 $fileContent = GeneralUtility::getUrl($url, 0, array(TYPO3_user_agent));
164
165 // Can not fetch url, throw an exception
166 if ($fileContent === false) {
167 throw new \RuntimeException('Can not fetch URL "' . $url . '". Possible reasons are network problems or misconfiguration.',
168 1344685036);
169 }
170
171 return $fileContent;
172 }
173 }