‪TYPO3CMS  10.4
ExtensionManagementService.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Psr\EventDispatcher\EventDispatcherInterface;
28 
33 {
37  protected ‪$downloadQueue;
38 
42  protected ‪$dependencyUtility;
43 
47  protected ‪$installUtility;
48 
53 
57  protected ‪$downloadUtility;
58 
62  protected ‪$automaticInstallationEnabled = true;
63 
67  protected ‪$skipDependencyCheck = false;
68 
72  protected ‪$eventDispatcher;
73 
74  public function ‪injectEventDispatcher(EventDispatcherInterface ‪$eventDispatcher)
75  {
76  $this->eventDispatcher = ‪$eventDispatcher;
77  }
78 
83  {
84  $this->downloadQueue = ‪$downloadQueue;
85  }
86 
91  {
92  $this->dependencyUtility = ‪$dependencyUtility;
93  }
94 
99  {
100  $this->installUtility = ‪$installUtility;
101  }
102 
107  {
108  $this->extensionModelUtility = ‪$extensionModelUtility;
109  }
110 
115  {
116  $this->downloadUtility = ‪$downloadUtility;
117  }
118 
122  public function ‪markExtensionForInstallation($extensionKey)
123  {
124  // We have to check for dependencies of the extension first, before marking it for installation
125  // because this extension might have dependencies, which need to be installed first
126  $this->installUtility->reloadAvailableExtensions();
127  $extension = $this->‪getExtension($extensionKey);
128  $this->dependencyUtility->checkDependencies($extension);
129  $this->downloadQueue->addExtensionToInstallQueue($extension);
130  }
131 
138  public function ‪markExtensionForCopy($extensionKey, $sourceFolder)
139  {
140  $this->downloadQueue->addExtensionToCopyQueue($extensionKey, $sourceFolder);
141  }
142 
148  public function ‪markExtensionForDownload(‪Extension $extension)
149  {
150  // We have to check for dependencies of the extension first, before marking it for download
151  // because this extension might have dependencies, which need to be downloaded and installed first
152  $this->dependencyUtility->checkDependencies($extension);
153  if (!$this->dependencyUtility->hasDependencyErrors()) {
154  $this->downloadQueue->addExtensionToQueue($extension);
155  }
156  }
157 
161  public function ‪markExtensionForUpdate(Extension $extension)
162  {
163  // We have to check for dependencies of the extension first, before marking it for download
164  // because this extension might have dependencies, which need to be downloaded and installed first
165  $this->dependencyUtility->checkDependencies($extension);
166  $this->downloadQueue->addExtensionToQueue($extension, 'update');
167  }
168 
175  {
176  $this->skipDependencyCheck = ‪$skipDependencyCheck;
177  }
178 
183  {
184  $this->automaticInstallationEnabled = (bool)‪$automaticInstallationEnabled;
185  }
186 
193  public function ‪installExtension(‪Extension $extension)
194  {
195  $this->‪downloadExtension($extension);
196  if (!$this->‪checkDependencies($extension)) {
197  return false;
198  }
199 
200  $downloadedDependencies = [];
201  $updatedDependencies = [];
202  $installQueue = [];
203 
204  // First resolve all dependencies and the sub-dependencies until all queues are empty as new extensions might be
205  // added each time
206  // Extensions have to be installed in reverse order. Extensions which were added at last are dependencies of
207  // earlier ones and need to be available before
208  while (!$this->downloadQueue->isCopyQueueEmpty()
209  || !$this->downloadQueue->isQueueEmpty('download')
210  || !$this->downloadQueue->isQueueEmpty('update')
211  ) {
212  // First copy all available extension
213  // This might change other queues again
214  $copyQueue = $this->downloadQueue->resetExtensionCopyStorage();
215  if (!empty($copyQueue)) {
216  $this->‪copyDependencies($copyQueue);
217  }
218  $installQueue = array_merge($this->downloadQueue->resetExtensionInstallStorage(), $installQueue);
219  // Get download and update information
220  $queue = $this->downloadQueue->resetExtensionQueue();
221  if (!empty($queue['download'])) {
222  $downloadedDependencies = array_merge($downloadedDependencies, $this->‪downloadDependencies($queue['download']));
223  }
224  $installQueue = array_merge($this->downloadQueue->resetExtensionInstallStorage(), $installQueue);
225  if ($this->automaticInstallationEnabled) {
226  if (!empty($queue['update'])) {
227  $this->‪downloadDependencies($queue['update']);
228  $updatedDependencies = array_merge($updatedDependencies, $this->‪uninstallDependenciesToBeUpdated($queue['update']));
229  }
230  $installQueue = array_merge($this->downloadQueue->resetExtensionInstallStorage(), $installQueue);
231  }
232  }
233 
234  // If there were any dependency errors we have to abort here
235  if ($this->dependencyUtility->hasDependencyErrors()) {
236  return false;
237  }
238 
239  // Attach extension to install queue
240  $this->downloadQueue->addExtensionToInstallQueue($extension);
241  $installQueue += $this->downloadQueue->resetExtensionInstallStorage();
242  $installedDependencies = [];
243  if ($this->automaticInstallationEnabled) {
244  $installedDependencies = $this->‪installDependencies($installQueue);
245  }
246 
247  return array_merge($downloadedDependencies, $updatedDependencies, $installedDependencies);
248  }
249 
255  public function ‪getDependencyErrors()
256  {
257  return $this->dependencyUtility->getDependencyErrors();
258  }
259 
265  public function ‪getExtension($extensionKey)
266  {
267  return $this->extensionModelUtility->mapExtensionArrayToModel(
268  $this->installUtility->enrichExtensionWithDetails($extensionKey)
269  );
270  }
271 
278  public function ‪isAvailable($extensionKey)
279  {
280  return $this->installUtility->isAvailable($extensionKey);
281  }
282 
290  public function ‪reloadPackageInformation($extensionKey)
291  {
292  $this->installUtility->reloadPackageInformation($extensionKey);
293  }
294 
300  protected function ‪downloadExtension(‪Extension $extension)
301  {
302  $this->‪downloadMainExtension($extension);
303  $this->‪setInExtensionRepository($extension->‪getExtensionKey());
304  }
305 
312  protected function ‪checkDependencies(‪Extension $extension)
313  {
314  $this->dependencyUtility->setSkipDependencyCheck($this->skipDependencyCheck);
315  $this->dependencyUtility->checkDependencies($extension);
316 
317  return !$this->dependencyUtility->hasDependencyErrors();
318  }
319 
327  protected function ‪setInExtensionRepository($extensionKey)
328  {
330  $path = $paths[$this->downloadUtility->getDownloadPath()] ?? '';
331  if (empty($path)) {
332  return;
333  }
334  $localExtensionStorage = $path . $extensionKey . '/Initialisation/Extensions/';
335  $this->dependencyUtility->setLocalExtensionStorage($localExtensionStorage);
336  }
337 
343  protected function ‪copyDependencies(array $copyQueue)
344  {
345  $installPaths = ‪Extension::returnAllowedInstallPaths();
346  foreach ($copyQueue as $extensionKey => $sourceFolder) {
347  $destination = $installPaths['Local'] . $extensionKey;
348  ‪GeneralUtility::mkdir($destination);
349  GeneralUtility::copyDirectory($sourceFolder . $extensionKey, $destination);
350  $this->‪markExtensionForInstallation($extensionKey);
351  $this->downloadQueue->removeExtensionFromCopyQueue($extensionKey);
352  }
353  }
354 
362  protected function ‪uninstallDependenciesToBeUpdated(array $updateQueue)
363  {
364  $resolvedDependencies = [];
365  foreach ($updateQueue as $extensionToUpdate) {
366  $this->installUtility->uninstall($extensionToUpdate->getExtensionKey());
367  $resolvedDependencies['updated'][$extensionToUpdate->getExtensionKey()] = $extensionToUpdate;
368  }
369  return $resolvedDependencies;
370  }
371 
378  protected function ‪installDependencies(array $installQueue)
379  {
380  if (empty($installQueue)) {
381  return [];
382  }
383  $this->eventDispatcher->dispatch(new BeforePackageActivationEvent($installQueue));
384  $resolvedDependencies = [];
385  $this->installUtility->install(...array_keys($installQueue));
386  foreach ($installQueue as $extensionKey => $_) {
387  if (!isset($resolvedDependencies['installed']) || !is_array($resolvedDependencies['installed'])) {
388  $resolvedDependencies['installed'] = [];
389  }
390  $resolvedDependencies['installed'][$extensionKey] = $extensionKey;
391  }
392  return $resolvedDependencies;
393  }
394 
402  protected function ‪downloadDependencies(array ‪$downloadQueue)
403  {
404  $resolvedDependencies = [];
405  foreach (‪$downloadQueue as $extensionToDownload) {
406  $this->downloadUtility->download($extensionToDownload);
407  $this->downloadQueue->removeExtensionFromQueue($extensionToDownload);
408  $resolvedDependencies['downloaded'][$extensionToDownload->getExtensionKey()] = $extensionToDownload;
409  $this->‪markExtensionForInstallation($extensionToDownload->getExtensionKey());
410  }
411  return $resolvedDependencies;
412  }
413 
420  public function ‪getAndResolveDependencies(‪Extension $extension)
421  {
422  $this->dependencyUtility->setSkipDependencyCheck($this->skipDependencyCheck);
423  $this->dependencyUtility->checkDependencies($extension);
424  $installQueue = $this->downloadQueue->getExtensionInstallStorage();
425  if (is_array($installQueue) && !empty($installQueue)) {
426  $installQueue = ['install' => $installQueue];
427  }
428  return array_merge($this->downloadQueue->getExtensionQueue(), $installQueue);
429  }
430 
438  public function ‪downloadMainExtension(‪Extension $extension)
439  {
440  // The extension object has a uid if the extension is not present in the system
441  // or an update of a present extension is triggered.
442  if ($extension->‪getUid()) {
443  $this->downloadUtility->download($extension);
444  }
445  }
446 }
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\returnAllowedInstallPaths
‪static array returnAllowedInstallPaths()
Definition: Extension.php:458
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\injectInstallUtility
‪injectInstallUtility(InstallUtility $installUtility)
Definition: ExtensionManagementService.php:90
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\copyDependencies
‪copyDependencies(array $copyQueue)
Definition: ExtensionManagementService.php:335
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$downloadUtility
‪DownloadUtility $downloadUtility
Definition: ExtensionManagementService.php:52
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\checkDependencies
‪bool checkDependencies(Extension $extension)
Definition: ExtensionManagementService.php:304
‪TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject\getUid
‪int null getUid()
Definition: AbstractDomainObject.php:67
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\setSkipDependencyCheck
‪setSkipDependencyCheck($skipDependencyCheck)
Definition: ExtensionManagementService.php:166
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension
Definition: Extension.php:29
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$extensionModelUtility
‪ExtensionModelUtility $extensionModelUtility
Definition: ExtensionManagementService.php:48
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\uninstallDependenciesToBeUpdated
‪array uninstallDependenciesToBeUpdated(array $updateQueue)
Definition: ExtensionManagementService.php:354
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$installUtility
‪InstallUtility $installUtility
Definition: ExtensionManagementService.php:44
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\markExtensionForDownload
‪markExtensionForDownload(Extension $extension)
Definition: ExtensionManagementService.php:140
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\injectDownloadQueue
‪injectDownloadQueue(DownloadQueue $downloadQueue)
Definition: ExtensionManagementService.php:74
‪TYPO3\CMS\Extensionmanager\Utility\ExtensionModelUtility
Definition: ExtensionModelUtility.php:28
‪TYPO3\CMS\Extensionmanager\Domain\Model\DownloadQueue
Definition: DownloadQueue.php:26
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$skipDependencyCheck
‪bool $skipDependencyCheck
Definition: ExtensionManagementService.php:60
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\markExtensionForUpdate
‪markExtensionForUpdate(Extension $extension)
Definition: ExtensionManagementService.php:153
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\setAutomaticInstallationEnabled
‪setAutomaticInstallationEnabled($automaticInstallationEnabled)
Definition: ExtensionManagementService.php:174
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\setInExtensionRepository
‪setInExtensionRepository($extensionKey)
Definition: ExtensionManagementService.php:319
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\markExtensionForInstallation
‪markExtensionForInstallation($extensionKey)
Definition: ExtensionManagementService.php:114
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\downloadDependencies
‪array downloadDependencies(array $downloadQueue)
Definition: ExtensionManagementService.php:394
‪TYPO3\CMS\Extensionmanager\Service
Definition: ComposerManifestProposalGenerator.php:18
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility
Definition: InstallUtility.php:55
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\installExtension
‪bool array installExtension(Extension $extension)
Definition: ExtensionManagementService.php:185
‪TYPO3\CMS\Extensionmanager\Utility\DependencyUtility
Definition: DependencyUtility.php:38
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\getExtensionKey
‪string getExtensionKey()
Definition: Extension.php:270
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\reloadPackageInformation
‪reloadPackageInformation($extensionKey)
Definition: ExtensionManagementService.php:282
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$eventDispatcher
‪EventDispatcherInterface $eventDispatcher
Definition: ExtensionManagementService.php:64
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\installDependencies
‪array installDependencies(array $installQueue)
Definition: ExtensionManagementService.php:370
‪TYPO3\CMS\Extensionmanager\Utility\DownloadUtility
Definition: DownloadUtility.php:29
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$automaticInstallationEnabled
‪bool $automaticInstallationEnabled
Definition: ExtensionManagementService.php:56
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\isAvailable
‪bool isAvailable($extensionKey)
Definition: ExtensionManagementService.php:270
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\markExtensionForCopy
‪markExtensionForCopy($extensionKey, $sourceFolder)
Definition: ExtensionManagementService.php:130
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\getAndResolveDependencies
‪array getAndResolveDependencies(Extension $extension)
Definition: ExtensionManagementService.php:412
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService
Definition: ExtensionManagementService.php:33
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:23
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\getDependencyErrors
‪array getDependencyErrors()
Definition: ExtensionManagementService.php:247
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\downloadExtension
‪downloadExtension(Extension $extension)
Definition: ExtensionManagementService.php:292
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\getExtension
‪Extension getExtension($extensionKey)
Definition: ExtensionManagementService.php:257
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$dependencyUtility
‪DependencyUtility $dependencyUtility
Definition: ExtensionManagementService.php:40
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\injectExtensionModelUtility
‪injectExtensionModelUtility(ExtensionModelUtility $extensionModelUtility)
Definition: ExtensionManagementService.php:98
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\injectEventDispatcher
‪injectEventDispatcher(EventDispatcherInterface $eventDispatcher)
Definition: ExtensionManagementService.php:66
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\injectDependencyUtility
‪injectDependencyUtility(DependencyUtility $dependencyUtility)
Definition: ExtensionManagementService.php:82
‪TYPO3\CMS\Core\Utility\GeneralUtility\mkdir
‪static bool mkdir($newFolder)
Definition: GeneralUtility.php:2005
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\returnInstallPaths
‪static array returnInstallPaths()
Definition: Extension.php:442
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\downloadMainExtension
‪downloadMainExtension(Extension $extension)
Definition: ExtensionManagementService.php:430
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$downloadQueue
‪DownloadQueue $downloadQueue
Definition: ExtensionManagementService.php:36
‪TYPO3\CMS\Core\Package\Event\BeforePackageActivationEvent
Definition: BeforePackageActivationEvent.php:24
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\injectDownloadUtility
‪injectDownloadUtility(DownloadUtility $downloadUtility)
Definition: ExtensionManagementService.php:106