03f9a19d7f62881987f90845ca3fcbea563bbf0a
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Classes / Service / ExtensionManagementService.php
1 <?php
2 namespace TYPO3\CMS\Extensionmanager\Service;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2012-2013 Susanne Moog, <susanne.moog@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the text file GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /**
30 * Service class for managing multiple step processes (dependencies for example)
31 *
32 * @author Susanne Moog <susanne.moog@typo3.org>
33 */
34 class ExtensionManagementService implements \TYPO3\CMS\Core\SingletonInterface {
35
36 /**
37 * @var \TYPO3\CMS\Extensionmanager\Domain\Model\DownloadQueue
38 * @inject
39 */
40 protected $downloadQueue;
41
42 /**
43 * @var \TYPO3\CMS\Extensionmanager\Utility\DependencyUtility
44 * @inject
45 */
46 protected $dependencyUtility;
47
48 /**
49 * @var \TYPO3\CMS\Extensionmanager\Utility\InstallUtility
50 * @inject
51 */
52 protected $installUtility;
53
54 /**
55 * @var \TYPO3\CMS\Extensionmanager\Utility\ListUtility
56 * @inject
57 */
58 protected $listUtility;
59
60 /**
61 * @var \TYPO3\CMS\Extensionmanager\Utility\DownloadUtility
62 * @inject
63 */
64 protected $downloadUtility;
65
66 /**
67 * @param string $extensionKey
68 * @return void
69 */
70 public function markExtensionForInstallation($extensionKey) {
71 $this->downloadQueue->addExtensionToInstallQueue($extensionKey);
72 }
73
74 /**
75 * Mark an extension for copy
76 *
77 * @param string $extensionKey
78 * @param string $sourceFolder
79 * @return void
80 */
81 public function markExtensionForCopy($extensionKey, $sourceFolder) {
82 $this->downloadQueue->addExtensionToCopyQueue($extensionKey, $sourceFolder);
83 }
84
85 /**
86 * Mark an extension for download
87 *
88 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
89 * @return void
90 */
91 public function markExtensionForDownload(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension) {
92 $this->downloadQueue->addExtensionToQueue($extension);
93 $this->dependencyUtility->buildExtensionDependenciesTree($extension);
94 }
95
96 /**
97 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
98 * @return void
99 */
100 public function markExtensionForUpdate(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension) {
101 $this->downloadQueue->addExtensionToQueue($extension, 'update');
102 $this->dependencyUtility->buildExtensionDependenciesTree($extension);
103 }
104
105 /**
106 * Resolve an extensions dependencies (download, copy and install dependent
107 * extensions) and install the extension
108 *
109 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
110 * @return array
111 */
112 public function resolveDependenciesAndInstall(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension) {
113 $downloadedDependencies = $this->downloadMainExtension($extension);
114 $extensionKey = $extension->getExtensionKey();
115 $this->setInExtensionRepository($extensionKey);
116 $this->dependencyUtility->buildExtensionDependenciesTree($extension);
117
118 $updatedDependencies = array();
119 $installedDependencies = array();
120 $queue = $this->downloadQueue->getExtensionQueue();
121 $copyQueue = $this->downloadQueue->getExtensionCopyStorage();
122
123 if (count($copyQueue) > 0) {
124 $this->copyDependencies($copyQueue);
125 }
126
127 if (array_key_exists('download', $queue)) {
128 $downloadedDependencies = array_merge($downloadedDependencies, $this->downloadDependencies($queue['download']));
129 }
130 if (array_key_exists('update', $queue)) {
131 $this->downloadDependencies($queue['update']);
132 $updatedDependencies = $this->uninstallDependenciesToBeUpdated($queue['update']);
133 }
134 // add extension at the end of the download queue
135 $this->downloadQueue->addExtensionToInstallQueue($extensionKey);
136 $installQueue = $this->downloadQueue->getExtensionInstallStorage();
137 if (count($installQueue) > 0) {
138 $installedDependencies = $this->installDependencies($installQueue);
139 }
140 return array_merge($downloadedDependencies, $updatedDependencies, $installedDependencies);
141 }
142
143 /**
144 * Sets the path to the repository in an extension
145 * (Initialisation/Extensions) depending on the extension
146 * that is currently installed
147 *
148 * @param string $extensionKey
149 */
150 protected function setInExtensionRepository($extensionKey) {
151 $paths = \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::returnInstallPaths();
152 $path = $paths[$this->downloadUtility->getDownloadPath()];
153 $localExtensionStorage = $path . $extensionKey . '/Initialisation/Extensions/';
154 $this->dependencyUtility->setLocalExtensionStorage($localExtensionStorage);
155 }
156
157 /**
158 * Copies locally provided extensions to typo3conf/ext
159 *
160 * @param array $copyQueue
161 * @return void
162 */
163 protected function copyDependencies(array $copyQueue) {
164 $installPaths = \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::returnAllowedInstallPaths();
165 foreach ($copyQueue as $extensionKey => $sourceFolder) {
166 $destination = $installPaths['Local'] . $extensionKey;
167 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($destination);
168 \TYPO3\CMS\Core\Utility\GeneralUtility::copyDirectory($sourceFolder . $extensionKey, $destination);
169 $this->markExtensionForInstallation($extensionKey);
170 $this->downloadQueue->removeExtensionFromCopyQueue($extensionKey);
171 }
172 }
173
174 /**
175 * Uninstall extensions that will be updated
176 * This is not strictly necessary but cleaner all in all
177 *
178 * @param array<Tx_Extensionmanager_Domain_Model_Extension> $updateQueue
179 * @return array
180 */
181 protected function uninstallDependenciesToBeUpdated(array $updateQueue) {
182 $resolvedDependencies = array();
183 foreach ($updateQueue as $extensionToUpdate) {
184 $this->installUtility->uninstall($extensionToUpdate->getExtensionKey());
185 $resolvedDependencies['updated'][$extensionToUpdate->getExtensionKey()] = $extensionToUpdate;
186 }
187 return $resolvedDependencies;
188 }
189
190 /**
191 * Install dependent extensions
192 *
193 * @param array $installQueue
194 * @return array
195 */
196 protected function installDependencies(array $installQueue) {
197 if (!empty($installQueue)) {
198 $this->emitWillInstallExtensions($installQueue);
199 }
200 $resolvedDependencies = array();
201 foreach ($installQueue as $extensionKey => $extensionDetails) {
202 $this->installUtility->install($extensionDetails);
203 if (!is_array($resolvedDependencies['installed'])) {
204 $resolvedDependencies['installed'] = array();
205 }
206 $resolvedDependencies['installed'][$extensionKey] = $extensionDetails;
207 }
208 return $resolvedDependencies;
209 }
210
211 /**
212 * Download dependencies
213 * expects an array of extension objects to download
214 *
215 * @param array<Tx_Extensionmanager_Domain_Model_Extension> $downloadQueue
216 * @return array
217 */
218 protected function downloadDependencies(array $downloadQueue) {
219 $resolvedDependencies = array();
220 foreach ($downloadQueue as $extensionToDownload) {
221 $this->downloadUtility->download($extensionToDownload);
222 $this->downloadQueue->removeExtensionFromQueue($extensionToDownload);
223 $resolvedDependencies['downloaded'][$extensionToDownload->getExtensionKey()] = $extensionToDownload;
224 $this->markExtensionForInstallation($extensionToDownload->getExtensionKey());
225 }
226 return $resolvedDependencies;
227 }
228
229 /**
230 * Get and resolve dependencies
231 *
232 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
233 * @return array
234 */
235 public function getAndResolveDependencies(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension) {
236 $this->dependencyUtility->buildExtensionDependenciesTree($extension);
237 $installQueue = $this->downloadQueue->getExtensionInstallStorage();
238 if (is_array($installQueue) && count($installQueue) > 0) {
239 $installQueue = array('install' => $installQueue);
240 }
241 return array_merge($this->downloadQueue->getExtensionQueue(), $installQueue);
242 }
243
244 /**
245 * Downloads the extension the user wants to install
246 * This is separated from downloading the dependencies
247 * as an extension is able to provide it's own dependencies
248 *
249 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
250 * @return array
251 */
252 public function downloadMainExtension(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension) {
253 $downloadedDependencies = array();
254 if ($extension->getUid()) {
255 $this->downloadQueue->addExtensionToQueue($extension);
256 $queue = $this->downloadQueue->getExtensionQueue();
257 $downloadedDependencies = $this->downloadDependencies($queue['download']);
258 }
259 return $downloadedDependencies;
260 }
261
262 /**
263 * @param array $installQueue
264 */
265 protected function emitWillInstallExtensions(array $installQueue) {
266 $this->getSignalSlotDispatcher()->dispatch(__CLASS__, 'willInstallExtensions', array($installQueue));
267 }
268
269 /**
270 * Get the SignalSlot dispatcher
271 *
272 * @return \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
273 */
274 protected function getSignalSlotDispatcher() {
275 if (!isset($this->signalSlotDispatcher)) {
276 $this->signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager')
277 ->get('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher');
278 }
279 return $this->signalSlotDispatcher;
280 }
281
282 }