/**
     * Renders a download link
     *
     * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
     * @return string the rendered a tag
     */
    public function render(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension)
    {
        $installPaths = \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::returnAllowedInstallPaths();
        if (empty($installPaths)) {
            return '';
        }
        $pathSelector = '<ul class="is-hidden">';
        foreach ($installPaths as $installPathType => $installPath) {
            $pathSelector .= '<li>
				<input type="radio" id="' . htmlspecialchars($extension->getExtensionKey()) . '-downloadPath-' . htmlspecialchars($installPathType) . '" name="' . htmlspecialchars($this->getFieldNamePrefix('downloadPath')) . '[downloadPath]" class="downloadPath" value="' . htmlspecialchars($installPathType) . '"' . ($installPathType == 'Local' ? ' checked="checked"' : '') . '/>
				<label for="' . htmlspecialchars($extension->getExtensionKey()) . '-downloadPath-' . htmlspecialchars($installPathType) . '">' . htmlspecialchars($installPathType) . '</label>
			</li>';
        }
        $pathSelector .= '</ul>';
        $uriBuilder = $this->controllerContext->getUriBuilder();
        $action = 'checkDependencies';
        $uriBuilder->reset();
        $uriBuilder->setFormat('json');
        $uri = $uriBuilder->uriFor($action, array('extension' => (int) $extension->getUid()), 'Download');
        $this->tag->addAttribute('data-href', $uri);
        $label = '
			<div class="btn-group">
				<button
					title="' . LocalizationUtility::translate('extensionList.downloadViewHelper.submit', 'extensionmanager') . '"
					type="submit"
					class="btn btn-default"
					value="' . LocalizationUtility::translate('extensionList.downloadViewHelper.submit', 'extensionmanager') . '"
				>
					<span class="t3-icon fa fa-cloud-download"></span>
				</button>
			</div>';
        $this->tag->setContent($label . $pathSelector);
        $this->tag->addAttribute('class', 'download');
        return '<div id="' . htmlspecialchars($extension->getExtensionKey()) . '-downloadFromTer" class="downloadFromTer">' . $this->tag->render() . '</div>';
    }
예제 #2
0
 /**
  * @return void
  */
 protected function setUp()
 {
     $this->downloadQueueMock = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Domain\Model\DownloadQueue::class, array('dummy'));
     $this->extensionMock = $this->getMock(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, array('dummy'));
     $this->extensionMock->setExtensionKey('foobar');
     $this->extensionMock->setVersion('1.0.0');
 }
예제 #3
0
 /**
  * @return void
  */
 public function setUp()
 {
     $this->downloadQueueMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Domain\\Model\\DownloadQueue', array('dummy'));
     $this->extensionMock = $this->getMock('TYPO3\\CMS\\Extensionmanager\\Domain\\Model\\Extension', array('dummy'));
     $this->extensionMock->setExtensionKey('foobar');
     $this->extensionMock->setVersion('1.0.0');
 }
 /**
  * Renders an install link
  *
  * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
  * @return string the rendered a tag
  */
 public function render($extension)
 {
     $uriBuilder = $this->controllerContext->getUriBuilder();
     $action = 'showAllVersions';
     $uri = $uriBuilder->reset()->uriFor($action, array('extensionKey' => $extension->getExtensionKey(), 'allVersions' => TRUE), 'List');
     $this->tag->addAttribute('href', $uri);
     $label = 'Show all versions';
     $this->tag->setContent($label);
     return $this->tag->render();
 }
 /**
  * Renders an install link
  *
  * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
  * @return string the rendered a tag
  */
 public function render($extension)
 {
     $uriBuilder = $this->controllerContext->getUriBuilder();
     $action = 'showAllVersions';
     $uri = $uriBuilder->reset()->uriFor($action, array('extensionKey' => $extension->getExtensionKey()), 'List');
     $this->tag->addAttribute('href', $uri);
     // Set class
     $this->tag->addAttribute('class', 'versions-all ui-icon ui-icon-triangle-1-s');
     $label = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('extensionList.showAllVersions.label', 'extensionmanager');
     $this->tag->setContent($label);
     return $this->tag->render();
 }
 /**
  * Finds and returns the suitable TYPO3 versions of an extension
  *
  * @param Extension $extension
  * @return string
  */
 public function render(Extension $extension)
 {
     /** @var Dependency $dependency */
     foreach ($extension->getDependencies() as $dependency) {
         if ($dependency->getIdentifier() === 'typo3') {
             $lowestVersion = $dependency->getLowestVersion();
             $highestVersion = $dependency->getHighestVersion();
             $cssClass = $this->isVersionSuitable($lowestVersion, $highestVersion) ? 'success' : 'default';
             return '<span class="label label-' . $cssClass . '">' . htmlspecialchars($lowestVersion) . ' - ' . htmlspecialchars($highestVersion) . '</span>';
         }
     }
     return '';
 }
예제 #7
0
 /**
  * Set the download path
  *
  * @param string $downloadPath
  * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
  * @return void
  */
 public function setDownloadPath($downloadPath)
 {
     if (!in_array($downloadPath, \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::returnAllowedInstallTypes())) {
         throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(htmlspecialchars($downloadPath) . ' not in allowed download paths', 1344766387);
     }
     $this->downloadPath = $downloadPath;
 }
예제 #8
0
 /**
  * Shows information about the distribution
  *
  * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
  */
 public function showAction(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension)
 {
     $extensionKey = $extension->getExtensionKey();
     // Check if extension/package is installed
     $active = $this->packageManager->isPackageActive($extensionKey);
     // Create link for extension configuration
     if ($active && file_exists(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($extensionKey) . 'ext_conf_template.txt')) {
         $uriBuilder = $this->controllerContext->getUriBuilder();
         $action = 'showConfigurationForm';
         $configurationLink = $uriBuilder->reset()->uriFor($action, array('extension' => array('key' => $extensionKey)), 'Configuration');
     } else {
         $configurationLink = FALSE;
     }
     $this->view->assign('distributionActive', $active);
     $this->view->assign('configurationLink', $configurationLink);
     $this->view->assign('extension', $extension);
 }
예제 #9
0
 /**
  * Method collects and stores extension version details into the database.
  *
  * @param \SplSubject|\TYPO3\CMS\Extensionmanager\Utility\Parser\AbstractExtensionXmlParser &$subject a subject notifying this observer
  * @return void
  */
 protected function loadIntoDatabase(\SplSubject &$subject)
 {
     // flush every 50 rows to database
     if ($this->sumRecords !== 0 && $this->sumRecords % 50 === 0) {
         GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('tx_extensionmanager_domain_model_extension')->bulkInsert('tx_extensionmanager_domain_model_extension', $this->arrRows, self::$fieldNames);
         $this->arrRows = [];
     }
     $versionRepresentations = \TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionStringToArray($subject->getVersion());
     // order must match that of self::$fieldNames!
     $this->arrRows[] = [$subject->getExtkey(), $subject->getVersion(), $versionRepresentations['version_int'], 0, (int) $subject->getAlldownloadcounter(), (int) $subject->getDownloadcounter(), !is_null($subject->getTitle()) ? $subject->getTitle() : '', $subject->getOwnerusername(), !is_null($subject->getAuthorname()) ? $subject->getAuthorname() : '', !is_null($subject->getAuthoremail()) ? $subject->getAuthoremail() : '', !is_null($subject->getAuthorcompany()) ? $subject->getAuthorcompany() : '', (int) $subject->getLastuploaddate(), $subject->getT3xfilemd5(), $this->repositoryUid, $this->extensionModel->getDefaultState($subject->getState() ?: ''), (int) $subject->getReviewstate(), $this->extensionModel->getCategoryIndexFromStringOrNumber($subject->getCategory() ?: ''), $subject->getDescription() ?: '', $subject->getDependencies() ?: '', $subject->getUploadcomment() ?: ''];
     ++$this->sumRecords;
 }
예제 #10
0
 /**
  * Method collects and stores extension version details into the database.
  *
  * @param \SplSubject|\TYPO3\CMS\Extensionmanager\Utility\Parser\AbstractExtensionXmlParser &$subject a subject notifying this observer
  * @return void
  */
 protected function loadIntoDatabase(\SplSubject &$subject)
 {
     // flush every 50 rows to database
     if ($this->sumRecords !== 0 && $this->sumRecords % 50 === 0) {
         $GLOBALS['TYPO3_DB']->exec_INSERTmultipleRows('tx_extensionmanager_domain_model_extension', self::$fieldNames, $this->arrRows, self::$fieldIndicesNoQuote);
         $this->arrRows = array();
     }
     $versionRepresentations = \TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionStringToArray($subject->getVersion());
     // order must match that of self::$fieldNames!
     $this->arrRows[] = array($subject->getExtkey(), $subject->getVersion(), $versionRepresentations['version_int'], 0, (int) $subject->getAlldownloadcounter(), (int) $subject->getDownloadcounter(), !is_null($subject->getTitle()) ? $subject->getTitle() : '', $subject->getOwnerusername(), !is_null($subject->getAuthorname()) ? $subject->getAuthorname() : '', !is_null($subject->getAuthoremail()) ? $subject->getAuthoremail() : '', !is_null($subject->getAuthorcompany()) ? $subject->getAuthorcompany() : '', (int) $subject->getLastuploaddate(), $subject->getT3xfilemd5(), $this->repositoryUid, $this->extensionModel->getDefaultState($subject->getState() ?: ''), (int) $subject->getReviewstate(), $this->extensionModel->getCategoryIndexFromStringOrNumber($subject->getCategory() ?: ''), $subject->getDescription() ?: '', $subject->getDependencies() ?: '', $subject->getUploadcomment() ?: '');
     ++$this->sumRecords;
 }
    /**
     * Renders a download link
     *
     * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
     * @return string the rendered a tag
     */
    public function render(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension)
    {
        $installPaths = \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::returnAllowedInstallPaths();
        $pathSelector = '<ul>';
        foreach ($installPaths as $installPathType => $installPath) {
            $pathSelector .= '<li>
				<input type="radio" id="' . $extension->getExtensionKey() . '-downloadPath-' . $installPathType . '" name="' . $this->getFieldNamePrefix('downloadPath') . '[downloadPath]" class="downloadPath" value="' . $installPathType . '"' . ($installPathType == 'Local' ? 'checked="checked"' : '') . '/>
				<label for="' . $extension->getExtensionKey() . '-downloadPath-' . $installPathType . '">' . $installPathType . '</label>
			</li>';
        }
        $pathSelector .= '</ul>';
        $uriBuilder = $this->controllerContext->getUriBuilder();
        $action = 'checkDependencies';
        $uriBuilder->reset();
        $uriBuilder->setFormat('json');
        $uri = $uriBuilder->uriFor($action, array('extension' => $extension->getUid()), 'Download');
        $this->tag->addAttribute('href', $uri);
        $label = '<input type="submit" value="Import and Install" />';
        $this->tag->setContent($label . $pathSelector);
        $this->tag->addAttribute('class', 'download');
        return '<div id="' . $extension->getExtensionKey() . '-downloadFromTer" class="downloadFromTer">' . $this->tag->render() . '</div>';
    }
 /**
  * Renders an install link
  *
  * @param string $extension
  * @return string the rendered a tag
  */
 public function render($extension)
 {
     if (!in_array($extension['type'], \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::returnAllowedInstallTypes())) {
         return '';
     }
     $uriBuilder = $this->controllerContext->getUriBuilder();
     $action = 'removeExtension';
     $uriBuilder->reset();
     $uriBuilder->setFormat('json');
     $uri = $uriBuilder->uriFor($action, array('extension' => $extension['key']), 'Action');
     $this->tag->addAttribute('href', $uri);
     $cssClass = 'removeExtension';
     if (\TYPO3\CMS\Core\Extension\ExtensionManager::isLoaded($extension['key'])) {
         $cssClass .= ' isLoadedWarning';
     }
     $this->tag->addAttribute('class', $cssClass);
     $label = 'Remove';
     $this->tag->setContent($label);
     return $this->tag->render();
 }
 /**
  * Renders an install link
  *
  * @param array $extension
  * @return string the rendered a tag
  */
 public function render($extension)
 {
     if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($extension['key'])) {
         return '<span class="btn btn-default disabled">' . IconUtility::getSpriteIcon('empty-empty') . '</span>';
     }
     if (!in_array($extension['type'], \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::returnAllowedInstallTypes()) || $extension['type'] === 'System') {
         return '<span class="btn btn-default disabled">' . IconUtility::getSpriteIcon('empty-empty') . '</span>';
     }
     $uriBuilder = $this->controllerContext->getUriBuilder();
     $action = 'removeExtension';
     $uriBuilder->reset();
     $uriBuilder->setFormat('json');
     $uri = $uriBuilder->uriFor($action, array('extension' => $extension['key']), 'Action');
     $this->tag->addAttribute('href', $uri);
     $cssClass = 'removeExtension btn btn-default';
     $this->tag->addAttribute('class', $cssClass);
     $this->tag->addAttribute('title', \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('extensionList.remove', 'extensionmanager'));
     $this->tag->setContent(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-edit-delete'));
     return $this->tag->render();
 }
 /**
  * Is the given path a valid path for extension installation
  *
  * @param string $path the absolute (!) path in question
  * @return boolean
  */
 public function isValidExtensionPath($path)
 {
     $allowedPaths = \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::returnAllowedInstallPaths();
     foreach ($allowedPaths as $allowedPath) {
         if (GeneralUtility::isFirstPartOfStr($path, $allowedPath)) {
             return TRUE;
         }
     }
     return FALSE;
 }
예제 #15
0
 /**
  * Returns the updateable version for an extension which also resolves dependencies.
  *
  * @internal
  * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionData
  * @return bool|\TYPO3\CMS\Extensionmanager\Domain\Model\Extension FALSE if no update available otherwise latest
  *                                                                 possible update
  */
 public function getUpdateableVersion(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionData)
 {
     // Only check for update for TER extensions
     $version = $extensionData->getIntegerVersion();
     /** @var $extensionUpdates[] \TYPO3\CMS\Extensionmanager\Domain\Model\Extension */
     $extensionUpdates = $this->extensionRepository->findByVersionRangeAndExtensionKeyOrderedByVersion($extensionData->getExtensionKey(), $version, 0, FALSE);
     if ($extensionUpdates->count() > 0) {
         foreach ($extensionUpdates as $extensionUpdate) {
             try {
                 $this->dependencyUtility->checkDependencies($extensionUpdate);
                 if (!$this->dependencyUtility->hasDependencyErrors()) {
                     return $extensionUpdate;
                 }
             } catch (ExtensionManagerException $e) {
             }
         }
     }
     return FALSE;
 }
예제 #16
0
 /**
  * Returns "System", "Global" or "Local" based on extension position in filesystem.
  *
  * @param PackageInterface $package
  * @return string
  */
 protected function getInstallTypeForPackage(PackageInterface $package)
 {
     foreach (\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::returnInstallPaths() as $installType => $installPath) {
         if (GeneralUtility::isFirstPartOfStr($package->getPackagePath(), $installPath)) {
             return $installType;
         }
     }
     return '';
 }
예제 #17
0
 /**
  * Checks if an update for an extension is available
  *
  * @internal
  * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionData
  * @return boolean
  */
 public function isUpdateAvailable(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionData)
 {
     // Only check for update for TER extensions
     $version = $extensionData->getIntegerVersion();
     /** @var $highestTerVersionExtension \TYPO3\CMS\Extensionmanager\Domain\Model\Extension */
     $highestTerVersionExtension = $this->extensionRepository->findHighestAvailableVersion($extensionData->getExtensionKey());
     if ($highestTerVersionExtension instanceof \TYPO3\CMS\Extensionmanager\Domain\Model\Extension) {
         $highestVersion = $highestTerVersionExtension->getIntegerVersion();
         if ($highestVersion > $version) {
             return TRUE;
         }
     }
     return FALSE;
 }
 /**
  * Downloads the extension the user wants to install
  * This is separated from downloading the dependencies
  * as an extension is able to provide it's own dependencies
  *
  * @param Extension $extension
  * @return void
  */
 public function downloadMainExtension(Extension $extension)
 {
     // The extension object has a uid if the extension is not present in the system
     // or an update of a present extension is triggered.
     if ($extension->getUid()) {
         $this->downloadUtility->download($extension);
     }
 }
예제 #19
0
 /**
  * Adds an extension to the install queue for later installation
  *
  * @param Extension $extension
  * @return void
  */
 public function addExtensionToInstallQueue($extension)
 {
     $this->extensionInstallStorage[$extension->getExtensionKey()] = $extension;
 }
예제 #20
0
 /**
  * Prepares an extension for import from TER
  * Uninstalls the extension if it is already loaded (case: update)
  * and reloads the caches.
  *
  * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
  * @return void
  */
 protected function prepareExtensionForImport(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension)
 {
     if (\TYPO3\CMS\Core\Extension\ExtensionManager::isLoaded($extension->getExtensionKey())) {
         \TYPO3\CMS\Core\Extension\ExtensionManager::unloadExtension($extension->getExtensionKey());
         $this->installUtility->reloadCaches();
     }
 }
예제 #21
0
 /**
  * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
  * @return void
  */
 public function buildExtensionDependenciesTree($extension)
 {
     $dependencies = $extension->getDependencies();
     $this->checkDependencies($dependencies);
 }
예제 #22
0
 /**
  * Returns the list of available, but not necessarily loaded extensions
  *
  * @return array Array with two sub-arrays, list array (all extensions with info) and category index
  * @see getInstExtList()
  */
 public function getAvailableExtensions()
 {
     $extensions = array();
     $paths = \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::returnInstallPaths();
     foreach ($paths as $installationType => $path) {
         try {
             if (is_dir($path)) {
                 $extList = \TYPO3\CMS\Core\Utility\GeneralUtility::get_dirs($path);
                 if (is_array($extList)) {
                     foreach ($extList as $extKey) {
                         $extensions[$extKey] = array('siteRelPath' => str_replace(PATH_site, '', $path . $extKey), 'type' => $installationType, 'key' => $extKey, 'ext_icon' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExtensionIcon($path . $extKey . '/'));
                     }
                 }
             }
         } catch (\Exception $e) {
             \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog($e->getMessage(), 'extensionmanager');
         }
     }
     return $extensions;
 }
예제 #23
0
 /**
  * Is the given path a valid path for extension installation
  *
  * @param string $path the absolute (!) path in question
  * @return bool
  */
 public function isValidExtensionPath($path)
 {
     $allowedPaths = Extension::returnAllowedInstallPaths();
     foreach ($allowedPaths as $allowedPath) {
         if (GeneralUtility::isFirstPartOfStr($path, $allowedPath)) {
             return true;
         }
     }
     return false;
 }
예제 #24
0
 /**
  * Checks if the extension is able to install at the demanded location
  *
  * @param string $location            The location
  * @param array  $allowedInstallTypes The allowed locations
  *
  * @return boolean
  * @throws \InvalidArgumentException
  */
 protected function checkInstallLocation($location)
 {
     $allowedInstallTypes = Extension::returnAllowedInstallTypes();
     $location = ucfirst(strtolower($location));
     if (!in_array($location, $allowedInstallTypes)) {
         if ($location === 'Global') {
             throw new InvalidArgumentException('Global installation is not allowed!');
         }
         if ($location === 'Local') {
             throw new InvalidArgumentException('Local installation is not allowed!');
         }
         if ($location === 'System') {
             throw new InvalidArgumentException('System installation is not allowed!');
         }
         throw new InvalidArgumentException(sprintf('Unknown location "%s"!', $location));
     }
 }
예제 #25
0
 /**
  * Checks dependencies for special cases (currently typo3 and php)
  *
  * @param Extension $extension
  * @return void
  */
 public function checkDependencies(Extension $extension)
 {
     $this->dependencyErrors = [];
     $dependencies = $extension->getDependencies();
     foreach ($dependencies as $dependency) {
         /** @var Dependency $dependency */
         $identifier = strtolower($dependency->getIdentifier());
         try {
             if (in_array($identifier, Dependency::$specialDependencies)) {
                 if (!$this->skipDependencyCheck) {
                     $methodName = 'check' . ucfirst($identifier) . 'Dependency';
                     $this->{$methodName}($dependency);
                 }
             } else {
                 if ($dependency->getType() === 'depends') {
                     $this->checkExtensionDependency($dependency);
                 }
             }
         } catch (Exception\UnresolvedDependencyException $e) {
             if (in_array($identifier, Dependency::$specialDependencies)) {
                 $extensionKey = $extension->getExtensionKey();
             } else {
                 $extensionKey = $identifier;
             }
             if (!isset($this->dependencyErrors[$extensionKey])) {
                 $this->dependencyErrors[$extensionKey] = [];
             }
             $this->dependencyErrors[$extensionKey][] = ['code' => $e->getCode(), 'message' => $e->getMessage()];
         }
     }
 }
예제 #26
0
 /**
  * Checks if an update for an extension is available
  *
  * @internal
  * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionData
  * @return boolean
  */
 public function isUpdateAvailable(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionData)
 {
     $isUpdateAvailable = FALSE;
     // Only check for update for TER extensions
     $version = $extensionData->getIntegerVersion();
     /** @var $highestTerVersionExtension \TYPO3\CMS\Extensionmanager\Domain\Model\Extension */
     $highestTerVersionExtension = $this->extensionRepository->findHighestAvailableVersion($extensionData->getExtensionKey());
     if ($highestTerVersionExtension instanceof \TYPO3\CMS\Extensionmanager\Domain\Model\Extension) {
         $highestVersion = $highestTerVersionExtension->getIntegerVersion();
         if ($highestVersion > $version) {
             $this->dependencyUtility->checkDependencies($highestTerVersionExtension);
             if (!$this->dependencyUtility->hasDependencyErrors()) {
                 $isUpdateAvailable = TRUE;
             }
         }
     }
     return $isUpdateAvailable;
 }
예제 #27
0
 /**
  * Remove an extension from download queue
  *
  * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
  * @param string $stack Stack to remove extension from (download, update or install)
  * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
  * @return void
  */
 public function removeExtensionFromQueue(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension, $stack = 'download')
 {
     if (!is_string($stack) || !in_array($stack, ['download', 'update'])) {
         throw new ExtensionManagerException('Stack has to be either "download" or "update"', 1342432104);
     }
     if (array_key_exists($stack, $this->extensionStorage) && is_array($this->extensionStorage[$stack])) {
         if (array_key_exists($extension->getExtensionKey(), $this->extensionStorage[$stack])) {
             unset($this->extensionStorage[$stack][$extension->getExtensionKey()]);
         }
     }
 }