Skip to content

Commit

Permalink
[BUGFIX] Streamline package management in PackageManager
Browse files Browse the repository at this point in the history
This bugfix resolves an issue that all available Packages
are scanned at each request. At the same time, it fixes
an issue related to runtimeActivatedPackages.

We now
- resolve package key with api usage
- distinguish between registered and available packages
- remove superfluous exception annotations
- prevent superfluous scans on getPackage() and isPackageAvailable() calls

Releases: master, 8.7
Resolves: #83820
Change-Id: I2b8bff3d4bb5287fd76418217653477c77467a8e
Reviewed-on: https://review.typo3.org/55687
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Tested-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
  • Loading branch information
IchHabRecht authored and neufeind committed Mar 12, 2018
1 parent 2b19fdb commit 56fc433
Showing 1 changed file with 29 additions and 20 deletions.
49 changes: 29 additions & 20 deletions typo3/sysext/core/Classes/Package/PackageManager.php
Expand Up @@ -396,7 +396,7 @@ protected function scanPackagePathsForExtensions()
protected function registerPackagesFromConfiguration(array $packages, $registerOnlyNewPackages = false, $packageStatesHasChanged = false)
{
foreach ($packages as $packageKey => $stateConfiguration) {
if ($registerOnlyNewPackages && $this->isPackageAvailable($packageKey)) {
if ($registerOnlyNewPackages && $this->isPackageRegistered($packageKey)) {
continue;
}

Expand Down Expand Up @@ -436,12 +436,11 @@ protected function registerPackagesFromConfiguration(array $packages, $registerO
* @param PackageInterface $package The Package to be registered
* @return PackageInterface
* @throws Exception\InvalidPackageStateException
* @throws Exception\PackageStatesFileNotWritableException
*/
public function registerPackage(PackageInterface $package)
{
$packageKey = $package->getPackageKey();
if ($this->isPackageAvailable($packageKey)) {
if ($this->isPackageRegistered($packageKey)) {
throw new Exception\InvalidPackageStateException('Package "' . $packageKey . '" is already registered.', 1338996122);
}

Expand Down Expand Up @@ -483,10 +482,10 @@ protected function unregisterPackageByPackageKey($packageKey)
*/
public function getPackageKeyFromComposerName($composerName)
{
if (isset($this->packageAliasMap[$composerName])) {
return $this->packageAliasMap[$composerName];
}
$lowercasedComposerName = strtolower($composerName);
if (isset($this->packageAliasMap[$lowercasedComposerName])) {
return $this->packageAliasMap[$lowercasedComposerName];
}
if (isset($this->composerNameToPackageKeyMap[$lowercasedComposerName])) {
return $this->composerNameToPackageKeyMap[$lowercasedComposerName];
}
Expand All @@ -504,10 +503,7 @@ public function getPackageKeyFromComposerName($composerName)
*/
public function getPackage($packageKey)
{
if (isset($this->packageAliasMap[$lowercasedPackageKey = strtolower($packageKey)])) {
$packageKey = $this->packageAliasMap[$lowercasedPackageKey];
}
if (!$this->isPackageAvailable($packageKey)) {
if (!$this->isPackageRegistered($packageKey) && !$this->isPackageAvailable($packageKey)) {
throw new Exception\UnknownPackageException('Package "' . $packageKey . '" is not available. Please check if the package exists and that the package key is correct (package keys are case sensitive).', 1166546734);
}
return $this->packages[$packageKey];
Expand All @@ -523,15 +519,17 @@ public function getPackage($packageKey)
*/
public function isPackageAvailable($packageKey)
{
if ($this->isPackageRegistered($packageKey)) {
return true;
}

// If activePackages is empty, the PackageManager is currently initializing
// thus packages should not be scanned
if (!$this->availablePackagesScanned && !empty($this->activePackages)) {
$this->scanAvailablePackages();
}
if (isset($this->packageAliasMap[$lowercasedPackageKey = strtolower($packageKey)])) {
$packageKey = $this->packageAliasMap[$lowercasedPackageKey];
}
return isset($this->packages[$packageKey]);

return $this->isPackageRegistered($packageKey);
}

/**
Expand All @@ -543,6 +541,8 @@ public function isPackageAvailable($packageKey)
*/
public function isPackageActive($packageKey)
{
$packageKey = $this->getPackageKeyFromComposerName($packageKey);

return isset($this->runtimeActivatedPackages[$packageKey]) || isset($this->packageStatesConfiguration['packages'][$packageKey]);
}

Expand Down Expand Up @@ -631,7 +631,6 @@ protected function registerTransientClassLoadingInformationForPackage(PackageInt
*
* @param string $packageKey
* @throws Exception
* @throws Exception\InvalidPackageStateException
* @throws Exception\ProtectedPackageKeyException
* @throws Exception\UnknownPackageException
*/
Expand Down Expand Up @@ -680,6 +679,19 @@ public function getActivePackages()
return array_merge($this->activePackages, $this->runtimeActivatedPackages);
}

/**
* Returns TRUE if a package was already registered or FALSE if it's not.
*
* @param string $packageKey
* @return bool
*/
protected function isPackageRegistered($packageKey)
{
$packageKey = $this->getPackageKeyFromComposerName($packageKey);

return isset($this->packages[$packageKey]);
}

/**
* Orders all active packages by comparing their dependencies. By this, the packages
* and package configurations arrays holds all packages in the correct
Expand Down Expand Up @@ -819,7 +831,7 @@ public function getAvailablePackages()
public function unregisterPackage(PackageInterface $package)
{
$packageKey = $package->getPackageKey();
if (!$this->isPackageAvailable($packageKey)) {
if (!$this->isPackageRegistered($packageKey)) {
throw new Exception\InvalidPackageStateException('Package "' . $packageKey . '" is not registered.', 1338996142);
}
$this->unregisterPackageByPackageKey($packageKey);
Expand All @@ -830,13 +842,10 @@ public function unregisterPackage(PackageInterface $package)
*
* @param string $packageKey
* @throws Exception\InvalidPackageStateException if the package isn't available
* @throws Exception\InvalidPackageKeyException if an invalid package key was passed
* @throws Exception\InvalidPackagePathException if an invalid package path was passed
* @throws Exception\InvalidPackageManifestException if no extension configuration file could be found
*/
public function reloadPackageInformation($packageKey)
{
if (!$this->isPackageAvailable($packageKey)) {
if (!$this->isPackageRegistered($packageKey)) {
throw new Exception\InvalidPackageStateException('Package "' . $packageKey . '" is not registered.', 1436201329);
}

Expand Down

0 comments on commit 56fc433

Please sign in to comment.