[BUGFIX] Prevent current extension version in update dialog
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Classes / Controller / DownloadController.php
1 <?php
2 namespace TYPO3\CMS\Extensionmanager\Controller;
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\Messaging\FlashMessage;
18 use TYPO3\CMS\Extensionmanager\Domain\Model\Extension;
19
20 /**
21 * Controller for actions related to the TER download of an extension
22 */
23 class DownloadController extends AbstractController {
24
25 /**
26 * @var \TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository
27 */
28 protected $extensionRepository;
29
30 /**
31 * @var \TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility
32 */
33 protected $fileHandlingUtility;
34
35 /**
36 * @var \TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService
37 */
38 protected $managementService;
39
40 /**
41 * @var \TYPO3\CMS\Extensionmanager\Utility\InstallUtility
42 */
43 protected $installUtility;
44
45 /**
46 * @var \TYPO3\CMS\Extensionmanager\Utility\DownloadUtility
47 */
48 protected $downloadUtility;
49
50 /**
51 * @var \TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility
52 */
53 protected $configurationUtility;
54
55 /**
56 * @param \TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository $extensionRepository
57 */
58 public function injectExtensionRepository(\TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository $extensionRepository) {
59 $this->extensionRepository = $extensionRepository;
60 }
61
62 /**
63 * @param \TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility $fileHandlingUtility
64 */
65 public function injectFileHandlingUtility(\TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility $fileHandlingUtility) {
66 $this->fileHandlingUtility = $fileHandlingUtility;
67 }
68
69 /**
70 * @param \TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService $managementService
71 */
72 public function injectManagementService(\TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService $managementService) {
73 $this->managementService = $managementService;
74 }
75
76 /**
77 * @param \TYPO3\CMS\Extensionmanager\Utility\InstallUtility $installUtility
78 */
79 public function injectInstallUtility(\TYPO3\CMS\Extensionmanager\Utility\InstallUtility $installUtility) {
80 $this->installUtility = $installUtility;
81 }
82
83 /**
84 * @param \TYPO3\CMS\Extensionmanager\Utility\DownloadUtility $downloadUtility
85 */
86 public function injectDownloadUtility(\TYPO3\CMS\Extensionmanager\Utility\DownloadUtility $downloadUtility) {
87 $this->downloadUtility = $downloadUtility;
88 }
89
90 /**
91 * @param \TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility $configurationUtility
92 */
93 public function injectConfigurationUtility(\TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility $configurationUtility) {
94 $this->configurationUtility = $configurationUtility;
95 }
96
97 /**
98 * Check extension dependencies
99 *
100 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
101 * @throws \Exception
102 */
103 public function checkDependenciesAction(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension) {
104 $message = '';
105 $title = '';
106 $hasDependencies = FALSE;
107 $hasErrors = FALSE;
108 if ($this->configurationUtility->getCurrentConfiguration('extensionmanager')['automaticInstallation']['value']) {
109 $action = 'installFromTer';
110 try {
111 $dependencyTypes = $this->managementService->getAndResolveDependencies($extension);
112 if (!empty($dependencyTypes)) {
113 $hasDependencies = TRUE;
114 $message = '<p>' . $this->translate('downloadExtension.dependencies.headline') . '</p>';
115 foreach ($dependencyTypes as $dependencyType => $dependencies) {
116 $extensions = '';
117 foreach ($dependencies as $extensionKey => $dependency) {
118 $extensions .= $this->translate('downloadExtension.dependencies.extensionWithVersion', array(
119 $extensionKey, $dependency->getVersion()
120 )) . '<br />';
121 }
122 $message .= $this->translate('downloadExtension.dependencies.typeHeadline',
123 array(
124 $this->translate('downloadExtension.dependencyType.' . $dependencyType),
125 $extensions
126 )
127 );
128 }
129 $title = $this->translate('downloadExtension.dependencies.resolveAutomatically');
130 }
131 $this->view->assign('dependencies', $dependencyTypes);
132 } catch (\Exception $e) {
133 $hasErrors = TRUE;
134 $title = $this->translate('downloadExtension.dependencies.errorTitle');
135 $message = $e->getMessage();
136 }
137 } else {
138 // if automatic installation is deactivated, no dependency check is needed (download only)
139 $action = 'installExtensionWithoutSystemDependencyCheck';
140 }
141 $this->view->assign('extension', $extension)
142 ->assign('action', $action)
143 ->assign('hasDependencies', $hasDependencies)
144 ->assign('hasErrors', $hasErrors)
145 ->assign('message', $message)
146 ->assign('title', $title);
147 }
148
149 /**
150 * Install an extension from TER action
151 *
152 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
153 * @param string $downloadPath
154 */
155 public function installFromTerAction(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension, $downloadPath) {
156 list($result, $errorMessages) = $this->installFromTer($extension, $downloadPath);
157 $emConfiguration = $this->configurationUtility->getCurrentConfiguration('extensionmanager');
158 $this->view
159 ->assign('result', $result)
160 ->assign('extension', $extension)
161 ->assign('installationTypeLanguageKey', (bool)$emConfiguration['automaticInstallation']['value'] ? '' : '.downloadOnly')
162 ->assign('unresolvedDependencies', $errorMessages);
163 }
164
165 /**
166 * Check extension dependencies with special dependencies
167 *
168 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
169 * @throws \Exception
170 */
171 public function installExtensionWithoutSystemDependencyCheckAction(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension) {
172 $this->managementService->setSkipDependencyCheck(TRUE);
173 $this->forward('installFromTer', NULL, NULL, array('extension' => $extension, 'downloadPath' => 'Local'));
174 }
175
176 /**
177 * Action for installing a distribution -
178 * redirects directly to configuration after installing
179 *
180 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
181 * @return void
182 */
183 public function installDistributionAction(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension) {
184 if (!\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('impexp')) {
185 $this->forward('distributions', 'List');
186 }
187 list($result, $errorMessages) = $this->installFromTer($extension);
188 if ($errorMessages) {
189 foreach ($errorMessages as $extensionKey => $messages) {
190 foreach ($messages as $message) {
191 $this->addFlashMessage(
192 $message['message'],
193 \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate(
194 'distribution.error.headline',
195 'extensionmanager',
196 array($extensionKey)
197 ),
198 \TYPO3\CMS\Core\Messaging\AbstractMessage::ERROR
199 );
200 }
201 }
202
203 // Redirect back to distributions list action
204 $this->redirect(
205 'distributions',
206 'List'
207 );
208 } else {
209 // FlashMessage that extension is installed
210 $this->addFlashMessage(
211 \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('distribution.welcome.message', 'extensionmanager')
212 . $extension->getExtensionKey(),
213 \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('distribution.welcome.headline', 'extensionmanager')
214 );
215
216 // Redirect to show action
217 $this->redirect(
218 'show',
219 'Distribution',
220 NULL,
221 array('extension' => $extension)
222 );
223 }
224 }
225
226 /**
227 * Update an extension. Makes no sanity check but directly searches highest
228 * available version from TER and updates. Update check is done by the list
229 * already. This method should only be called if we are sure that there is
230 * an update.
231 *
232 * @return string
233 */
234 protected function updateExtensionAction() {
235 $extensionKey = $this->request->getArgument('extension');
236 $version = $this->request->getArgument('version');
237 $extension = $this->extensionRepository->findOneByExtensionKeyAndVersion($extensionKey, $version);
238 if (!$extension instanceof Extension) {
239 $extension = $this->extensionRepository->findHighestAvailableVersion($extensionKey);
240 }
241 $installedExtensions = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getLoadedExtensionListArray();
242 try {
243 if (in_array($extensionKey, $installedExtensions, TRUE)) {
244 // To resolve new dependencies the extension is installed again
245 $this->managementService->installExtension($extension);
246 } else {
247 $this->managementService->downloadMainExtension($extension);
248 }
249 $this->addFlashMessage(
250 $this->translate('extensionList.updateFlashMessage.body', array($extensionKey)),
251 $this->translate('extensionList.updateFlashMessage.title')
252 );
253 } catch (\Exception $e) {
254 $this->addFlashMessage($e->getMessage(), '', FlashMessage::ERROR);
255 }
256
257 return '';
258 }
259
260 /**
261 * Show update comments for extensions that can be updated.
262 * Fetches update comments for all versions between the current
263 * installed and the highest version.
264 *
265 * @return void
266 */
267 protected function updateCommentForUpdatableVersionsAction() {
268 $extensionKey = $this->request->getArgument('extension');
269 $versionStart = $this->request->getArgument('integerVersionStart');
270 $versionStop = $this->request->getArgument('integerVersionStop');
271 $updateComments = array();
272 /** @var Extension[] $updatableVersions */
273 $updatableVersions = $this->extensionRepository->findByVersionRangeAndExtensionKeyOrderedByVersion(
274 $extensionKey,
275 $versionStart,
276 $versionStop,
277 FALSE
278 );
279 $highestPossibleVersion = FALSE;
280
281 foreach ($updatableVersions as $updatableVersion) {
282 if ($highestPossibleVersion === FALSE) {
283 $highestPossibleVersion = $updatableVersion->getVersion();
284 }
285 $updateComments[$updatableVersion->getVersion()] = $updatableVersion->getUpdateComment();
286 }
287 $this->view->assign('updateComments', $updateComments)
288 ->assign('extensionKey', $extensionKey)
289 ->assign('version', $highestPossibleVersion);
290 }
291
292 /**
293 * Install an extension from TER
294 * Downloads the extension, resolves dependencies and installs it
295 *
296 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
297 * @param string $downloadPath
298 * @return array
299 */
300 protected function installFromTer(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension, $downloadPath = 'Local') {
301 $result = FALSE;
302 $errorMessages = array();
303 try {
304 $this->downloadUtility->setDownloadPath($downloadPath);
305 $this->managementService->setAutomaticInstallationEnabled($this->configurationUtility->getCurrentConfiguration('extensionmanager')['automaticInstallation']['value']);
306 if (($result = $this->managementService->installExtension($extension)) === FALSE) {
307 $errorMessages = $this->managementService->getDependencyErrors();
308 }
309 } catch (\TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException $e) {
310 $errorMessages = array(
311 $extension->getExtensionKey() => array(
312 array(
313 'code' => $e->getCode(),
314 'message' => $e->getMessage(),
315 )
316 ),
317 );
318 }
319
320 return array($result, $errorMessages);
321 }
322
323 }