/** * 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>'; }
/** * @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'); }
/** * @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 ''; }
/** * 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; }
/** * 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); }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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 ''; }
/** * 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); } }
/** * Adds an extension to the install queue for later installation * * @param Extension $extension * @return void */ public function addExtensionToInstallQueue($extension) { $this->extensionInstallStorage[$extension->getExtensionKey()] = $extension; }
/** * 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(); } }
/** * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension * @return void */ public function buildExtensionDependenciesTree($extension) { $dependencies = $extension->getDependencies(); $this->checkDependencies($dependencies); }
/** * 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; }
/** * 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; }
/** * 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)); } }
/** * 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()]; } } }
/** * 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; }
/** * 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()]); } } }