/** * @test * @return void */ public function updateWizardDoesNotRunIfCssStyledContentIsInstalled() { $this->packageManagerProphecy->isPackageActive('fluid_styled_content')->willReturn(true); $this->packageManagerProphecy->isPackageActive('css_styled_content')->willReturn(true); $description = ''; $this->assertFalse($this->updateWizard->checkForUpdate($description)); }
/** * Activates all packages that are configured in root composer.json or are required * * @param bool $removeInactivePackages */ public function generatePackageStatesCommand($removeInactivePackages = FALSE) { try { $installationPackages = $this->getPackagesFromRootComposerFile(); } catch (\Exception $e) { $this->outputLine('<error>' . $e->getMessage() . '</error>'); $this->quit(1); return; } foreach ($this->packageManager->getAvailablePackages() as $package) { if (isset($installationPackages[$package->getPackageKey()]) || $package->isProtected() || $package instanceof Package && $package->isPartOfMinimalUsableSystem()) { $this->packageManager->activatePackage($package->getPackageKey()); } else { try { $this->packageManager->deactivatePackage($package->getPackageKey()); } catch (\UnexpectedValueException $exception) { $this->outputLine('<info>Error while deactivating package %s. Exception: %s</info>', array($package->getPackageKey(), $exception->getMessage())); } if ($removeInactivePackages) { $this->packageManager->unregisterPackage($package); GeneralUtility::flushDirectory($package->getPackagePath()); $this->outputLine('Removed Package: ' . $package->getPackageKey()); } } } $this->packageManager->forceSortAndSavePackageStates(); }
/** * Returns the package meta data object of this package. * * @return MetaData */ public function getPackageMetaData() { if ($this->packageMetaData === null) { $this->packageMetaData = new MetaData($this->getPackageKey()); $this->packageMetaData->setDescription($this->getValueFromComposerManifest('description')); $this->packageMetaData->setVersion($this->getValueFromComposerManifest('version')); $requirements = $this->getValueFromComposerManifest('require'); if ($requirements !== null) { foreach ($requirements as $requirement => $version) { $packageKey = $this->packageManager->getPackageKeyFromComposerName($requirement); // dynamically migrate 'cms' dependency to 'core' dependency // see also \TYPO3\CMS\Extensionmanager\Utility\ExtensionModelUtility::convertDependenciesToObjects if ($packageKey === 'cms') { GeneralUtility::deprecationLog('Extension "' . $this->packageKey . '" defines a dependency on ext:cms, which has been removed. Please remove the dependency.'); $packageKey = 'core'; } $constraint = new MetaData\PackageConstraint(MetaData::CONSTRAINT_TYPE_DEPENDS, $packageKey); $this->packageMetaData->addConstraint($constraint); } } $suggestions = $this->getValueFromComposerManifest('suggest'); if ($suggestions !== null) { foreach ($suggestions as $suggestion => $version) { $packageKey = $this->packageManager->getPackageKeyFromComposerName($suggestion); $constraint = new MetaData\PackageConstraint(MetaData::CONSTRAINT_TYPE_SUGGESTS, $packageKey); $this->packageMetaData->addConstraint($constraint); } } } return $this->packageMetaData; }
/** * Constructor * * @param \TYPO3\Flow\Package\PackageManager $packageManager the package manager which knows this package * @param string $packageKey Key of this package * @param string $packagePath Absolute path to the location of the package's composer manifest * @param string $classesPath Path the classes of the package are in, relative to $packagePath. Optional, read from Composer manifest if not set. * @param string $manifestPath Path the composer manifest of the package, relative to $packagePath. Optional, defaults to ''. * @throws \TYPO3\Flow\Package\Exception\InvalidPackageKeyException if an invalid package key was passed * @throws \TYPO3\Flow\Package\Exception\InvalidPackagePathException if an invalid package path was passed * @throws \TYPO3\Flow\Package\Exception\InvalidPackageManifestException if no composer manifest file could be found */ public function __construct(\TYPO3\Flow\Package\PackageManager $packageManager, $packageKey, $packagePath, $classesPath = NULL, $manifestPath = '') { if (!\TYPO3\CMS\Core\Package\PackageManager::isPackageKeyValid($packageKey)) { throw new \TYPO3\Flow\Package\Exception\InvalidPackageKeyException('"' . $packageKey . '" is not a valid package key.', 1217959511); } if (!(@is_dir($packagePath) || \TYPO3\Flow\Utility\Files::is_link($packagePath) && is_dir(\TYPO3\Flow\Utility\Files::getNormalizedPath($packagePath)))) { throw new \TYPO3\Flow\Package\Exception\InvalidPackagePathException(sprintf('Tried to instantiate a package object for package "%s" with a non-existing package path "%s". Either the package does not exist anymore, or the code creating this object contains an error.', $packageKey, $packagePath), 1166631890); } if (substr($packagePath, -1, 1) !== '/') { throw new \TYPO3\Flow\Package\Exception\InvalidPackagePathException(sprintf('The package path "%s" provided for package "%s" has no trailing forward slash.', $packagePath, $packageKey), 1166633722); } if ($classesPath[1] === '/') { throw new \TYPO3\Flow\Package\Exception\InvalidPackagePathException(sprintf('The package classes path provided for package "%s" has a leading forward slash.', $packageKey), 1334841321); } if (!@file_exists($packagePath . $manifestPath . 'ext_emconf.php')) { throw new \TYPO3\Flow\Package\Exception\InvalidPackageManifestException(sprintf('No ext_emconf file found for package "%s". Please create one at "%sext_emconf.php".', $packageKey, $manifestPath), 1360403545); } $this->packageManager = $packageManager; $this->manifestPath = $manifestPath; $this->packageKey = $packageKey; $this->packagePath = \TYPO3\Flow\Utility\Files::getNormalizedPath($packagePath); $this->classesPath = \TYPO3\Flow\Utility\Files::getNormalizedPath(\TYPO3\Flow\Utility\Files::concatenatePaths(array($this->packagePath, self::DIRECTORY_CLASSES))); try { $this->getComposerManifest(); } catch (\TYPO3\Flow\Package\Exception\MissingPackageManifestException $exception) { $this->getExtensionEmconf($packageKey, $this->packagePath); } $this->loadFlagsFromComposerManifest(); if ($this->objectManagementEnabled === NULL) { $this->objectManagementEnabled = FALSE; } }
/** * Warm up essential caches such as class and core caches * * @param bool $triggerRequire * @return bool */ public function warmupEssentialCaches($triggerRequire = FALSE) { try { $this->cacheManager->getCache('cache_classes'); } catch (NoSuchCacheException $e) { $this->logger->warning('Warmup skipped due to lack of classes cache'); return FALSE; } // TODO: This currently only builds the classes cache! Find a way to build other system caches as well (like reflection caches, datamap caches …) // package namespace and aliases caches are implicitly built in extended bootstrap before we reach this point $phpParser = new PhpParser(); foreach ($this->packageManager->getActivePackages() as $package) { $classFiles = GeneralUtility::getAllFilesAndFoldersInPath(array(), $package->getClassesPath(), 'php'); foreach ($classFiles as $classFile) { try { $parsedResult = $phpParser->parseClassFile($classFile); $this->writeCacheEntryForClass($parsedResult->getFullyQualifiedClassName(), $classFile); } catch (ParsingException $e) { $this->logger->warning('Class file "' . PathUtility::stripPathSitePrefix($classFile) . '" does not contain a class definition. Skipping …'); } } } $this->packageManager->injectCoreCache($this->cacheManager->getCache('cache_core')); $this->packageManager->populatePackageCache(); return TRUE; }
/** * Unloads given extension * * Warning: This method only works if the ugrade wizard to transform * localconf.php to LocalConfiguration.php was already run * * @param string $extensionKey Extension key to remove * @return void * @throws \RuntimeException */ public static function unloadExtension($extensionKey) { if (!static::$packageManager->isPackageActive($extensionKey)) { throw new \RuntimeException('Extension not loaded', 1342345487); } static::$packageManager->deactivatePackage($extensionKey); }
/** * Enrich the output of getAvailableExtensions() with an array key installed = 1 if an extension is loaded. * * @param array $availableExtensions * @return array */ public function getAvailableAndInstalledExtensions(array $availableExtensions) { foreach ($this->packageManager->getActivePackages() as $extKey => $_) { if (isset($availableExtensions[$extKey])) { $availableExtensions[$extKey]['installed'] = TRUE; } } return $availableExtensions; }
/** * Activates all packages that are configured in root composer.json or are required * * @param bool $removeInactivePackages */ public function generatePackageStatesCommand($removeInactivePackages = FALSE) { $installationPackages = $this->getPackagesFromRootComposerFile(); foreach ($this->packageManager->getAvailablePackages() as $package) { if (in_array($package->getPackageKey(), $installationPackages) || $package->isProtected() || $package instanceof Package && $package->isPartOfMinimalUsableSystem()) { $this->packageManager->activatePackage($package->getPackageKey()); } else { $this->packageManager->deactivatePackage($package->getPackageKey()); if ($removeInactivePackages) { $this->packageManager->unregisterPackage($package); GeneralUtility::flushDirectory($package->getPackagePath()); $this->outputLine('Removed Package: ' . $package->getPackageKey()); } } } $this->packageManager->forceSortAndSavePackageStates(); }
/** * 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); }
/** * @test */ public function deletePackageRemovesPackageFromAvailableAndActivePackagesAndDeletesThePackageDirectory() { $this->createPackage('Acme.YetAnotherTestPackage'); $this->assertTrue($this->packageManager->isPackageActive('Acme.YetAnotherTestPackage')); $this->assertTrue($this->packageManager->isPackageAvailable('Acme.YetAnotherTestPackage')); $this->packageManager->deletePackage('Acme.YetAnotherTestPackage'); $this->assertFalse($this->packageManager->isPackageActive('Acme.YetAnotherTestPackage')); $this->assertFalse($this->packageManager->isPackageAvailable('Acme.YetAnotherTestPackage')); }
/** * Update language file for each extension * * @param string $localesToUpdate Comma separated list of locales that needs to be updated * @return void * @deprecated Use LanguageCommandController (language:update) instead. will be removed two versions after 6.2 */ public function updateCommand($localesToUpdate = '') { /** @var $updateTranslationService \TYPO3\CMS\Lang\Service\UpdateTranslationService */ $updateTranslationService = $this->objectManager->get('TYPO3\\CMS\\Lang\\Service\\UpdateTranslationService'); /** @var $languageRepository \TYPO3\CMS\Lang\Domain\Repository\LanguageRepository */ $languageRepository = $this->objectManager->get('TYPO3\\CMS\\Lang\\Domain\\Repository\\LanguageRepository'); $locales = array(); if (!empty($localesToUpdate)) { $locales = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $localesToUpdate, TRUE); } else { $languages = $languageRepository->findSelected(); foreach ($languages as $language) { /** @var $language \TYPO3\CMS\Lang\Domain\Model\Language */ $locales[] = $language->getLocale(); } } $this->packageManager = $this->objectManager->get('TYPO3\\CMS\\Core\\Package\\PackageManager'); $this->emitPackagesMayHaveChangedSignal(); foreach ($this->packageManager->getAvailablePackages() as $package) { $updateTranslationService->updateTranslation($package->getPackageKey(), $locales); } }
/** * Creates users based on given array. * * @param $packageKey * @param $configuration * @param $configurationController */ public function createCLIUsers($packageKey, $configuration, $configurationController) { // Only create CLI users on configuration save of template bootstrap package if (TemplateBootstrapUtility::getPackageKey() !== $packageKey) { return; } // Get cli user names that supposedly need to be created $userNames = GeneralUtility::trimExplode(',', $configuration['createCLIUsers']['value']); foreach ($userNames as $userName) { $cliUserName = '******' . $userName; $cliUserNameQuoted = $GLOBALS['TYPO3_DB']->fullQuoteStr($cliUserName, 'be_users'); // Check, if user exists already $userExistsResult = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'be_users', 'username='******'TYPO3_DB']->sql_error()) { PostInstallInfoLogger::log('Failed to check whether BE user "' . $cliUserName . '" exists. Therefore cancelled. Error: ' . $GLOBALS['TYPO3_DB']->sql_error(), PostInstallInfoLogger::MESSAGE_TYPE_SYSTEM_ERROR); continue; } // User exists - (re-) activate, in case it has been deleted previously if ($GLOBALS['TYPO3_DB']->sql_num_rows($userExistsResult) > 0) { $existingUserRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($userExistsResult); if ($existingUserRow['deleted']) { $GLOBALS['TYPO3_DB']->exec_UPDATEquery('be_users', 'uid=' . $existingUserRow['uid'], array('deleted' => 0)); $updatedError = $GLOBALS['TYPO3_DB']->sql_error(); if ($updatedError) { PostInstallInfoLogger::log('Failed to reactivate (un-delete) BE user "' . $cliUserName . '". Error: ' . $GLOBALS['TYPO3_DB']->sql_error(), PostInstallInfoLogger::MESSAGE_TYPE_SYSTEM_ERROR); } else { PostInstallInfoLogger::log('Reactivated (un-deleted) BE user "' . $cliUserName . '"' . $GLOBALS['TYPO3_DB']->sql_error(), PostInstallInfoLogger::MESSAGE_TYPE_OK); } } // Skip to next user(name) as this one was handled by simply reactivating it. continue; } // Create user $saltedPassword = md5($this->getRandomPassword()); if (PackageManager::isPackageActive('saltedpasswords')) { $saltingInstance = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance(); $saltedPassword = $saltingInstance->getHashedPassword($saltedPassword); } $createdSqlResult = $GLOBALS['TYPO3_DB']->exec_INSERTquery('be_users', array('crdate' => time(), 'tstamp' => time(), 'cruser_id' => $GLOBALS['BE_USER']->user['uid'], 'username' => $cliUserName, 'password' => $saltedPassword)); // Failed to create user if ($GLOBALS['TYPO3_DB']->sql_error()) { PostInstallInfoLogger::log('Failed to create BE user "' . $cliUserName . '". Error: ' . $GLOBALS['TYPO3_DB']->sql_error(), PostInstallInfoLogger::MESSAGE_TYPE_SYSTEM_ERROR); // User successfully created } else { PostInstallInfoLogger::log('Created BE user "' . $cliUserName . '"', PostInstallInfoLogger::MESSAGE_TYPE_OK); } } // foreach user that needs to be created }
/** * Remove an extension (delete the directory) * * @param string $extension * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException * @return void */ public function removeExtension($extension) { $absolutePath = $this->fileHandlingUtility->getAbsoluteExtensionPath($extension); if ($this->fileHandlingUtility->isValidExtensionPath($absolutePath)) { if ($this->packageManager->isPackageAvailable($extension)) { // Package manager deletes the extension and removes the entry from PackageStates.php $this->packageManager->deletePackage($extension); } else { // The extension is not listed in PackageStates.php, we can safely remove it $this->fileHandlingUtility->removeDirectory($absolutePath); } } else { throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('No valid extension path given.', 1342875724); } }
/** * Get all class names inside this namespace and return them as array. * This has to be done by iterating over class files for TYPO3 CMS * as the Extbase Reflection Service cannot return all implementations * of Fluid AbstractViewHelpers * * @param string $namespace * @return array Array of all class names inside a given namespace. */ protected function getClassNamesInNamespace($namespace) { $packageKey = $this->getPackageKeyFromNamespace($namespace); $viewHelperClassFiles = GeneralUtility::getAllFilesAndFoldersInPath(array(), $this->packageManager->getPackage($packageKey)->getPackagePath() . 'Classes/ViewHelpers/', 'php'); $affectedViewHelperClassNames = array(); foreach ($viewHelperClassFiles as $filePathAndFilename) { $potentialViewHelperClassName = $this->getClassNameFromNamespaceAndPath($namespace, $filePathAndFilename); if (is_subclass_of($potentialViewHelperClassName, 'TYPO3\\CMS\\Fluid\\Core\\ViewHelper\\AbstractViewHelper')) { $classReflection = new \ReflectionClass($potentialViewHelperClassName); if ($classReflection->isAbstract() === TRUE) { continue; } $affectedViewHelperClassNames[] = $potentialViewHelperClassName; } } sort($affectedViewHelperClassNames); return $affectedViewHelperClassNames; }
/** * Asserts the expected differences are found */ protected function assertFixtureExtensionChangesAreFound() { $package = $this->packageManager->getPackage($this->fixtureExtensionKey); $repository = ExtensionInformationRepositoryFactory::create(); $this->assertSame($this->expectedDifferences, $repository->findDifferentExtensionInformation($package)); }
/** * @return \TYPO3\CMS\Core\Package\PackageInterface * @api */ public function getPackage() { return $this->packageManager->getPackage($this->extensionKey); }
/** * To enable writing of the package states file the package states * migration needs to override eventual failsafe blocks. * This will be used during installation process. */ public function forceSortAndSavePackageStates() { parent::sortAndSavePackageStates(); }