‪TYPO3CMS  11.5
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 
97  {
98  $this->downloadQueue = ‪$downloadQueue;
99  }
100 
104  public function ‪injectDependencyUtility(DependencyUtility ‪$dependencyUtility)
105  {
106  $this->dependencyUtility = ‪$dependencyUtility;
107  }
108 
112  public function ‪injectInstallUtility(InstallUtility ‪$installUtility)
113  {
114  $this->installUtility = ‪$installUtility;
115  }
116 
120  public function ‪markExtensionForInstallation($extensionKey)
121  {
122  // We have to check for dependencies of the extension first, before marking it for installation
123  // because this extension might have dependencies, which need to be installed first
124  $this->installUtility->reloadAvailableExtensions();
125  $extension = $this->‪getExtension($extensionKey);
126  $this->dependencyUtility->checkDependencies($extension);
127  $this->downloadQueue->addExtensionToInstallQueue($extension);
128  }
129 
135  public function ‪markExtensionForDownload(‪Extension $extension)
136  {
137  // We have to check for dependencies of the extension first, before marking it for download
138  // because this extension might have dependencies, which need to be downloaded and installed first
139  $this->dependencyUtility->checkDependencies($extension);
140  if (!$this->dependencyUtility->hasDependencyErrors()) {
141  $this->downloadQueue->addExtensionToQueue($extension);
142  }
143  }
144 
148  public function ‪markExtensionForUpdate(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  $this->downloadQueue->addExtensionToQueue($extension, 'update');
154  }
155 
162  {
163  $this->skipDependencyCheck = ‪$skipDependencyCheck;
164  }
165 
170  {
171  $this->automaticInstallationEnabled = (bool)‪$automaticInstallationEnabled;
172  }
173 
180  public function ‪installExtension(‪Extension $extension)
181  {
182  $this->‪downloadMainExtension($extension);
183  if (!$this->‪checkDependencies($extension)) {
184  return false;
185  }
186 
187  $downloadedDependencies = [];
188  $updatedDependencies = [];
189  $installQueue = [];
190 
191  // First resolve all dependencies and the sub-dependencies until all queues are empty as new extensions might be
192  // added each time
193  // Extensions have to be installed in reverse order. Extensions which were added at last are dependencies of
194  // earlier ones and need to be available before
195  while (!$this->downloadQueue->isQueueEmpty('download')
196  || !$this->downloadQueue->isQueueEmpty('update')
197  ) {
198  $installQueue = array_merge($this->downloadQueue->resetExtensionInstallStorage(), $installQueue);
199  // Get download and update information
200  $queue = $this->downloadQueue->resetExtensionQueue();
201  if (!empty($queue['download'])) {
202  $downloadedDependencies = array_merge($downloadedDependencies, $this->‪downloadDependencies($queue['download']));
203  }
204  $installQueue = array_merge($this->downloadQueue->resetExtensionInstallStorage(), $installQueue);
205  if ($this->automaticInstallationEnabled) {
206  if (!empty($queue['update'])) {
207  $this->‪downloadDependencies($queue['update']);
208  $updatedDependencies = array_merge($updatedDependencies, $this->‪uninstallDependenciesToBeUpdated($queue['update']));
209  }
210  $installQueue = array_merge($this->downloadQueue->resetExtensionInstallStorage(), $installQueue);
211  }
212  }
213 
214  // If there were any dependency errors we have to abort here
215  if ($this->dependencyUtility->hasDependencyErrors()) {
216  return false;
217  }
218 
219  // Attach extension to install queue
220  $this->downloadQueue->addExtensionToInstallQueue($extension);
221  $installQueue += $this->downloadQueue->resetExtensionInstallStorage();
222  $installedDependencies = [];
223  if ($this->automaticInstallationEnabled) {
224  $installedDependencies = $this->‪installDependencies($installQueue);
225  }
226 
227  return array_merge($downloadedDependencies, $updatedDependencies, $installedDependencies);
228  }
229 
235  public function ‪getDependencyErrors()
236  {
237  return $this->dependencyUtility->getDependencyErrors();
238  }
239 
245  public function ‪getExtension($extensionKey)
246  {
248  $this->installUtility->enrichExtensionWithDetails($extensionKey)
249  );
250  }
251 
258  public function ‪isAvailable($extensionKey)
259  {
260  return $this->installUtility->isAvailable($extensionKey);
261  }
262 
270  public function ‪reloadPackageInformation($extensionKey)
271  {
272  $this->installUtility->reloadPackageInformation($extensionKey);
273  }
274 
281  protected function ‪checkDependencies(‪Extension $extension)
282  {
283  $this->dependencyUtility->setSkipDependencyCheck($this->skipDependencyCheck);
284  $this->dependencyUtility->checkDependencies($extension);
285 
286  return !$this->dependencyUtility->hasDependencyErrors();
287  }
288 
296  protected function ‪uninstallDependenciesToBeUpdated(array $updateQueue)
297  {
298  $resolvedDependencies = [];
299  foreach ($updateQueue as $extensionToUpdate) {
300  $this->installUtility->uninstall($extensionToUpdate->getExtensionKey());
301  $resolvedDependencies['updated'][$extensionToUpdate->getExtensionKey()] = $extensionToUpdate;
302  }
303  return $resolvedDependencies;
304  }
305 
312  protected function ‪installDependencies(array $installQueue)
313  {
314  if (empty($installQueue)) {
315  return [];
316  }
317  $this->eventDispatcher->dispatch(new BeforePackageActivationEvent($installQueue));
318  $resolvedDependencies = [];
319  $this->installUtility->install(...array_keys($installQueue));
320  foreach ($installQueue as $extensionKey => $_) {
321  if (!isset($resolvedDependencies['installed']) || !is_array($resolvedDependencies['installed'])) {
322  $resolvedDependencies['installed'] = [];
323  }
324  $resolvedDependencies['installed'][$extensionKey] = $extensionKey;
325  }
326  return $resolvedDependencies;
327  }
328 
336  protected function ‪downloadDependencies(array ‪$downloadQueue)
337  {
338  $resolvedDependencies = [];
339  foreach (‪$downloadQueue as $extensionToDownload) {
340  $this->‪rawDownload($extensionToDownload);
341  $this->downloadQueue->removeExtensionFromQueue($extensionToDownload);
342  $resolvedDependencies['downloaded'][$extensionToDownload->getExtensionKey()] = $extensionToDownload;
343  $this->‪markExtensionForInstallation($extensionToDownload->getExtensionKey());
344  }
345  return $resolvedDependencies;
346  }
347 
354  public function ‪getAndResolveDependencies(‪Extension $extension)
355  {
356  $this->dependencyUtility->setSkipDependencyCheck($this->skipDependencyCheck);
357  $this->dependencyUtility->checkDependencies($extension);
358  $installQueue = $this->downloadQueue->getExtensionInstallStorage();
359  if (is_array($installQueue) && !empty($installQueue)) {
360  $installQueue = ['install' => $installQueue];
361  }
362  return array_merge($this->downloadQueue->getExtensionQueue(), $installQueue);
363  }
364 
372  public function ‪downloadMainExtension(‪Extension $extension)
373  {
374  // The extension object has a uid if the extension is not present in the system
375  // or an update of a present extension is triggered.
376  if ($extension->‪getUid()) {
377  $this->‪rawDownload($extension);
378  }
379  }
380 
381  protected function ‪rawDownload(‪Extension $extension): void
382  {
383  if (
385  || (bool)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('extensionmanager', 'offlineMode')
386  ) {
387  throw new ‪ExtensionManagerException('Extension Manager is in offline mode. No TER connection available.', 1437078620);
388  }
389 
390  $remoteIdentifier = $extension->‪getRemoteIdentifier();
391 
392  if ($this->remoteRegistry->hasRemote($remoteIdentifier)) {
393  $this->remoteRegistry
394  ->getRemote($remoteIdentifier)
395  ->downloadExtension(
396  $extension->‪getExtensionKey(),
397  $extension->‪getVersion(),
398  $this->fileHandlingUtility,
399  $extension->‪getMd5hash(),
400  $this->downloadPath
401  );
402  }
403  }
404 
411  public function ‪setDownloadPath(string ‪$downloadPath): void
412  {
414  throw new ExtensionManagerException(‪$downloadPath . ' not in allowed download paths', 1344766387);
415  }
416  $this->downloadPath = ‪$downloadPath;
417  }
418 }
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$downloadPath
‪string $downloadPath
Definition: ExtensionManagementService.php:71
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\injectInstallUtility
‪injectInstallUtility(InstallUtility $installUtility)
Definition: ExtensionManagementService.php:103
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\getRemoteIdentifier
‪getRemoteIdentifier()
Definition: Extension.php:614
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\checkDependencies
‪bool checkDependencies(Extension $extension)
Definition: ExtensionManagementService.php:272
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\__construct
‪__construct(RemoteRegistry $remoteRegistry, FileHandlingUtility $fileHandlingUtility)
Definition: ExtensionManagementService.php:73
‪TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject\getUid
‪int null getUid()
Definition: AbstractDomainObject.php:67
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\setSkipDependencyCheck
‪setSkipDependencyCheck($skipDependencyCheck)
Definition: ExtensionManagementService.php:152
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension
Definition: Extension.php:28
‪TYPO3\CMS\Core\Configuration\ExtensionConfiguration
Definition: ExtensionConfiguration.php:45
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\uninstallDependenciesToBeUpdated
‪array uninstallDependenciesToBeUpdated(array $updateQueue)
Definition: ExtensionManagementService.php:287
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$installUtility
‪InstallUtility $installUtility
Definition: ExtensionManagementService.php:47
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\markExtensionForDownload
‪markExtensionForDownload(Extension $extension)
Definition: ExtensionManagementService.php:126
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\injectDownloadQueue
‪injectDownloadQueue(DownloadQueue $downloadQueue)
Definition: ExtensionManagementService.php:87
‪TYPO3\CMS\Extensionmanager\Domain\Model\DownloadQueue
Definition: DownloadQueue.php:26
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\createFromExtensionArray
‪static Extension createFromExtensionArray(array $extensionArray)
Definition: Extension.php:625
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$skipDependencyCheck
‪bool $skipDependencyCheck
Definition: ExtensionManagementService.php:55
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\markExtensionForUpdate
‪markExtensionForUpdate(Extension $extension)
Definition: ExtensionManagementService.php:139
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\setAutomaticInstallationEnabled
‪setAutomaticInstallationEnabled($automaticInstallationEnabled)
Definition: ExtensionManagementService.php:160
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\markExtensionForInstallation
‪markExtensionForInstallation($extensionKey)
Definition: ExtensionManagementService.php:111
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\downloadDependencies
‪array downloadDependencies(array $downloadQueue)
Definition: ExtensionManagementService.php:327
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility
Definition: FileHandlingUtility.php:36
‪TYPO3\CMS\Extensionmanager\Service
Definition: ComposerManifestProposalGenerator.php:18
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility
Definition: InstallUtility.php:56
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\getMd5hash
‪string getMd5hash()
Definition: Extension.php:430
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\installExtension
‪bool array installExtension(Extension $extension)
Definition: ExtensionManagementService.php:171
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\rawDownload
‪rawDownload(Extension $extension)
Definition: ExtensionManagementService.php:372
‪TYPO3\CMS\Extensionmanager\Utility\DependencyUtility
Definition: DependencyUtility.php:35
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\getVersion
‪string getVersion()
Definition: Extension.php:398
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\getExtensionKey
‪string getExtensionKey()
Definition: Extension.php:269
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\reloadPackageInformation
‪reloadPackageInformation($extensionKey)
Definition: ExtensionManagementService.php:261
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$eventDispatcher
‪EventDispatcherInterface $eventDispatcher
Definition: ExtensionManagementService.php:59
‪TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
Definition: ExtensionManagerException.php:23
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\installDependencies
‪array installDependencies(array $installQueue)
Definition: ExtensionManagementService.php:303
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$automaticInstallationEnabled
‪bool $automaticInstallationEnabled
Definition: ExtensionManagementService.php:51
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\isAvailable
‪bool isAvailable($extensionKey)
Definition: ExtensionManagementService.php:249
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\getAndResolveDependencies
‪array getAndResolveDependencies(Extension $extension)
Definition: ExtensionManagementService.php:345
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService
Definition: ExtensionManagementService.php:36
‪TYPO3\CMS\Core\Core\Environment\isComposerMode
‪static bool isComposerMode()
Definition: Environment.php:152
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$fileHandlingUtility
‪FileHandlingUtility $fileHandlingUtility
Definition: ExtensionManagementService.php:63
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:22
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\getDependencyErrors
‪array getDependencyErrors()
Definition: ExtensionManagementService.php:226
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:43
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\getExtension
‪Extension getExtension($extensionKey)
Definition: ExtensionManagementService.php:236
‪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:50
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\injectDependencyUtility
‪injectDependencyUtility(DependencyUtility $dependencyUtility)
Definition: ExtensionManagementService.php:95
‪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:475
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\downloadMainExtension
‪downloadMainExtension(Extension $extension)
Definition: ExtensionManagementService.php:363
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\$downloadQueue
‪DownloadQueue $downloadQueue
Definition: ExtensionManagementService.php:39
‪TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService\setDownloadPath
‪setDownloadPath(string $downloadPath)
Definition: ExtensionManagementService.php:402
‪TYPO3\CMS\Core\Package\Event\BeforePackageActivationEvent
Definition: BeforePackageActivationEvent.php:24
‪TYPO3\CMS\Extensionmanager\Remote\RemoteRegistry
Definition: RemoteRegistry.php:26