‪TYPO3CMS  ‪main
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;
31 
36 {
40  protected ‪$downloadQueue;
41 
45  protected ‪$dependencyUtility;
46 
50  protected ‪$installUtility;
51 
56 
60  protected ‪$skipDependencyCheck = false;
61 
65  protected ‪$eventDispatcher;
66 
70  protected ‪$fileHandlingUtility;
71 
75  protected ‪$remoteRegistry;
76 
80  protected ‪$downloadPath = 'Local';
81 
83  {
84  $this->remoteRegistry = ‪$remoteRegistry;
85  $this->fileHandlingUtility = ‪$fileHandlingUtility;
86  }
87 
88  public function ‪injectEventDispatcher(EventDispatcherInterface ‪$eventDispatcher)
89  {
90  $this->eventDispatcher = ‪$eventDispatcher;
91  }
92 
94  {
95  $this->downloadQueue = ‪$downloadQueue;
96  }
97 
99  {
100  $this->dependencyUtility = ‪$dependencyUtility;
101  }
102 
104  {
105  $this->installUtility = ‪$installUtility;
106  }
107 
111  public function ‪markExtensionForInstallation($extensionKey)
112  {
113  // We have to check for dependencies of the extension first, before marking it for installation
114  // because this extension might have dependencies, which need to be installed first
115  $this->installUtility->reloadAvailableExtensions();
116  $extension = $this->‪getExtension($extensionKey);
117  $this->dependencyUtility->checkDependencies($extension);
118  $this->downloadQueue->addExtensionToInstallQueue($extension);
119  }
120 
124  public function ‪markExtensionForDownload(‪Extension $extension)
125  {
126  // We have to check for dependencies of the extension first, before marking it for download
127  // because this extension might have dependencies, which need to be downloaded and installed first
128  $this->dependencyUtility->checkDependencies($extension);
129  if (!$this->dependencyUtility->hasDependencyErrors()) {
130  $this->downloadQueue->addExtensionToQueue($extension);
131  }
132  }
133 
134  public function ‪markExtensionForUpdate(‪Extension $extension)
135  {
136  // We have to check for dependencies of the extension first, before marking it for download
137  // because this extension might have dependencies, which need to be downloaded and installed first
138  $this->dependencyUtility->checkDependencies($extension);
139  $this->downloadQueue->addExtensionToQueue($extension, 'update');
140  }
141 
148  {
149  $this->skipDependencyCheck = ‪$skipDependencyCheck;
150  }
151 
156  {
157  $this->automaticInstallationEnabled = (bool)‪$automaticInstallationEnabled;
158  }
159 
165  public function ‪installExtension(‪Extension $extension)
166  {
167  $this->‪downloadMainExtension($extension);
168  if (!$this->‪checkDependencies($extension)) {
169  return false;
170  }
171 
172  $downloadedDependencies = [];
173  $updatedDependencies = [];
174  $installQueue = [];
175 
176  // First resolve all dependencies and the sub-dependencies until all queues are empty as new extensions might be
177  // added each time
178  // Extensions have to be installed in reverse order. Extensions which were added at last are dependencies of
179  // earlier ones and need to be available before
180  while (!$this->downloadQueue->isQueueEmpty('download')
181  || !$this->downloadQueue->isQueueEmpty('update')
182  ) {
183  $installQueue = array_merge($this->downloadQueue->resetExtensionInstallStorage(), $installQueue);
184  // Get download and update information
185  $queue = $this->downloadQueue->resetExtensionQueue();
186  if (!empty($queue['download'])) {
187  $downloadedDependencies = array_merge($downloadedDependencies, $this->‪downloadDependencies($queue['download']));
188  }
189  $installQueue = array_merge($this->downloadQueue->resetExtensionInstallStorage(), $installQueue);
190  if ($this->automaticInstallationEnabled) {
191  if (!empty($queue['update'])) {
192  $this->‪downloadDependencies($queue['update']);
193  $updatedDependencies = array_merge($updatedDependencies, $this->‪uninstallDependenciesToBeUpdated($queue['update']));
194  }
195  $installQueue = array_merge($this->downloadQueue->resetExtensionInstallStorage(), $installQueue);
196  }
197  }
198 
199  // If there were any dependency errors we have to abort here
200  if ($this->dependencyUtility->hasDependencyErrors()) {
201  return false;
202  }
203 
204  // Attach extension to install queue
205  $this->downloadQueue->addExtensionToInstallQueue($extension);
206  $installQueue += $this->downloadQueue->resetExtensionInstallStorage();
207  $installedDependencies = [];
208  if ($this->automaticInstallationEnabled) {
209  $installedDependencies = $this->‪installDependencies($installQueue);
210  }
211 
212  return array_merge($downloadedDependencies, $updatedDependencies, $installedDependencies);
213  }
214 
220  public function ‪getDependencyErrors()
221  {
222  return $this->dependencyUtility->getDependencyErrors();
223  }
224 
230  public function ‪getExtension($extensionKey)
231  {
233  $this->installUtility->enrichExtensionWithDetails($extensionKey)
234  );
235  }
236 
243  public function ‪isAvailable($extensionKey)
244  {
245  return $this->installUtility->isAvailable($extensionKey);
246  }
247 
255  public function ‪reloadPackageInformation($extensionKey)
256  {
257  $this->installUtility->reloadPackageInformation($extensionKey);
258  }
259 
265  protected function ‪checkDependencies(‪Extension $extension)
266  {
267  $this->dependencyUtility->setSkipDependencyCheck($this->skipDependencyCheck);
268  $this->dependencyUtility->checkDependencies($extension);
269 
270  return !$this->dependencyUtility->hasDependencyErrors();
271  }
272 
280  protected function ‪uninstallDependenciesToBeUpdated(array $updateQueue)
281  {
282  $resolvedDependencies = [];
283  foreach ($updateQueue as $extensionToUpdate) {
284  $this->installUtility->uninstall($extensionToUpdate->getExtensionKey());
285  $resolvedDependencies['updated'][$extensionToUpdate->getExtensionKey()] = $extensionToUpdate;
286  }
287  return $resolvedDependencies;
288  }
289 
295  protected function ‪installDependencies(array $installQueue)
296  {
297  if (empty($installQueue)) {
298  return [];
299  }
300  $this->eventDispatcher->dispatch(new BeforePackageActivationEvent($installQueue));
301  $resolvedDependencies = [];
302  $this->installUtility->install(...array_keys($installQueue));
303  foreach ($installQueue as $extensionKey => $_) {
304  if (!isset($resolvedDependencies['installed']) || !is_array($resolvedDependencies['installed'])) {
305  $resolvedDependencies['installed'] = [];
306  }
307  $resolvedDependencies['installed'][$extensionKey] = $extensionKey;
308  }
309  return $resolvedDependencies;
310  }
311 
319  protected function ‪downloadDependencies(array ‪$downloadQueue)
320  {
321  $resolvedDependencies = [];
322  foreach (‪$downloadQueue as $extensionToDownload) {
323  $this->‪rawDownload($extensionToDownload);
324  $this->downloadQueue->removeExtensionFromQueue($extensionToDownload);
325  $resolvedDependencies['downloaded'][$extensionToDownload->getExtensionKey()] = $extensionToDownload;
326  $this->‪markExtensionForInstallation($extensionToDownload->getExtensionKey());
327  }
328  return $resolvedDependencies;
329  }
330 
336  public function ‪getAndResolveDependencies(Extension $extension)
337  {
338  $this->dependencyUtility->setSkipDependencyCheck($this->skipDependencyCheck);
339  $this->dependencyUtility->checkDependencies($extension);
340  $installQueue = $this->downloadQueue->getExtensionInstallStorage();
341  if (is_array($installQueue) && !empty($installQueue)) {
342  $installQueue = ['install' => $installQueue];
343  }
344  return array_merge($this->downloadQueue->getExtensionQueue(), $installQueue);
345  }
346 
352  public function ‪downloadMainExtension(‪Extension $extension)
353  {
354  // The extension object has a uid if the extension is not present in the system
355  // or an update of a present extension is triggered.
356  if ($extension->‪getUid()) {
357  $this->‪rawDownload($extension);
358  }
359  }
360 
361  protected function ‪rawDownload(‪Extension $extension): void
362  {
363  if (
365  || (bool)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('extensionmanager', 'offlineMode')
366  ) {
367  throw new ‪ExtensionManagerException('Extension Manager is in offline mode. No TER connection available.', 1437078620);
368  }
369 
370  $remoteIdentifier = $extension->‪getRemoteIdentifier();
371 
372  if ($this->remoteRegistry->hasRemote($remoteIdentifier)) {
373  $this->remoteRegistry
374  ->getRemote($remoteIdentifier)
375  ->downloadExtension(
376  $extension->‪getExtensionKey(),
377  $extension->‪getVersion(),
378  $this->fileHandlingUtility,
379  $extension->‪getMd5hash(),
380  $this->downloadPath
381  );
382  }
383  }
384 
390  public function ‪setDownloadPath(string ‪$downloadPath): void
391  {
393  throw new ExtensionManagerException(‪$downloadPath . ' not in allowed download paths', 1344766387);
394  }
395  $this->downloadPath = ‪$downloadPath;
396  }
397 }
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$downloadPath
‪string $downloadPath
Definition: ExtensionManagementService.php:71
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\injectInstallUtility
‪injectInstallUtility(InstallUtility $installUtility)
Definition: ExtensionManagementService.php:94
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\getRemoteIdentifier
‪getRemoteIdentifier()
Definition: Extension.php:582
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\checkDependencies
‪bool checkDependencies(Extension $extension)
Definition: ExtensionManagementService.php:256
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\__construct
‪__construct(RemoteRegistry $remoteRegistry, FileHandlingUtility $fileHandlingUtility)
Definition: ExtensionManagementService.php:73
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\setSkipDependencyCheck
‪setSkipDependencyCheck($skipDependencyCheck)
Definition: ExtensionManagementService.php:138
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension
Definition: Extension.php:28
‪TYPO3\CMS\Core\Configuration\ExtensionConfiguration
Definition: ExtensionConfiguration.php:47
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\uninstallDependenciesToBeUpdated
‪array uninstallDependenciesToBeUpdated(array $updateQueue)
Definition: ExtensionManagementService.php:271
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$installUtility
‪InstallUtility $installUtility
Definition: ExtensionManagementService.php:47
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\markExtensionForDownload
‪markExtensionForDownload(Extension $extension)
Definition: ExtensionManagementService.php:115
‪TYPO3\CMS\Core\Core\Environment\isComposerMode
‪static isComposerMode()
Definition: Environment.php:137
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\injectDownloadQueue
‪injectDownloadQueue(DownloadQueue $downloadQueue)
Definition: ExtensionManagementService.php:84
‪TYPO3\CMS\Extensionmanager\Domain\Model\DownloadQueue
Definition: DownloadQueue.php:26
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$skipDependencyCheck
‪bool $skipDependencyCheck
Definition: ExtensionManagementService.php:55
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\markExtensionForUpdate
‪markExtensionForUpdate(Extension $extension)
Definition: ExtensionManagementService.php:125
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\setAutomaticInstallationEnabled
‪setAutomaticInstallationEnabled($automaticInstallationEnabled)
Definition: ExtensionManagementService.php:146
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\markExtensionForInstallation
‪markExtensionForInstallation($extensionKey)
Definition: ExtensionManagementService.php:102
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\downloadDependencies
‪array downloadDependencies(array $downloadQueue)
Definition: ExtensionManagementService.php:310
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility
Definition: FileHandlingUtility.php:38
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\createFromExtensionArray
‪static createFromExtensionArray(array $extensionArray)
Definition: Extension.php:590
‪TYPO3\CMS\Extensionmanager\Service
Definition: ComposerManifestProposalGenerator.php:18
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility
Definition: InstallUtility.php:57
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\getMd5hash
‪string getMd5hash()
Definition: Extension.php:427
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\installExtension
‪bool array installExtension(Extension $extension)
Definition: ExtensionManagementService.php:156
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\rawDownload
‪rawDownload(Extension $extension)
Definition: ExtensionManagementService.php:352
‪TYPO3\CMS\Extensionmanager\Utility\DependencyUtility
Definition: DependencyUtility.php:35
‪TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface\getUid
‪getUid()
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\getVersion
‪string getVersion()
Definition: Extension.php:395
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\getExtensionKey
‪string getExtensionKey()
Definition: Extension.php:269
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\reloadPackageInformation
‪reloadPackageInformation($extensionKey)
Definition: ExtensionManagementService.php:246
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$eventDispatcher
‪EventDispatcherInterface $eventDispatcher
Definition: ExtensionManagementService.php:59
‪TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
Definition: ExtensionManagerException.php:24
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\installDependencies
‪array installDependencies(array $installQueue)
Definition: ExtensionManagementService.php:286
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$automaticInstallationEnabled
‪bool $automaticInstallationEnabled
Definition: ExtensionManagementService.php:51
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\isAvailable
‪bool isAvailable($extensionKey)
Definition: ExtensionManagementService.php:234
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\getAndResolveDependencies
‪array getAndResolveDependencies(Extension $extension)
Definition: ExtensionManagementService.php:327
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService
Definition: ExtensionManagementService.php:36
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$fileHandlingUtility
‪FileHandlingUtility $fileHandlingUtility
Definition: ExtensionManagementService.php:63
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:23
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\getDependencyErrors
‪array getDependencyErrors()
Definition: ExtensionManagementService.php:211
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\getExtension
‪Extension getExtension($extensionKey)
Definition: ExtensionManagementService.php:221
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$dependencyUtility
‪DependencyUtility $dependencyUtility
Definition: ExtensionManagementService.php:43
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\injectEventDispatcher
‪injectEventDispatcher(EventDispatcherInterface $eventDispatcher)
Definition: ExtensionManagementService.php:79
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\injectDependencyUtility
‪injectDependencyUtility(DependencyUtility $dependencyUtility)
Definition: ExtensionManagementService.php:89
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$remoteRegistry
‪RemoteRegistry $remoteRegistry
Definition: ExtensionManagementService.php:67
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\returnAllowedInstallTypes
‪static array returnAllowedInstallTypes()
Definition: Extension.php:452
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\downloadMainExtension
‪downloadMainExtension(Extension $extension)
Definition: ExtensionManagementService.php:343
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$downloadQueue
‪DownloadQueue $downloadQueue
Definition: ExtensionManagementService.php:39
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\setDownloadPath
‪setDownloadPath(string $downloadPath)
Definition: ExtensionManagementService.php:381
‪TYPO3\CMS\Core\Package\Event\BeforePackageActivationEvent
Definition: BeforePackageActivationEvent.php:24
‪TYPO3\CMS\Extensionmanager\Remote\RemoteRegistry
Definition: RemoteRegistry.php:26