Skip to content

Commit

Permalink
[TASK] Add PHPStan type hints in PackageManager
Browse files Browse the repository at this point in the history
Resolves: #101808
Releases: main, 12.4
Change-Id: Iab938e0608a5547838d8b0cbc40c795e7653f929
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/80795
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: core-ci <typo3@b13.com>
  • Loading branch information
ohader authored and lolli42 committed Aug 31, 2023
1 parent 3b1fe2d commit 54d22e2
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 44 deletions.
87 changes: 46 additions & 41 deletions typo3/sysext/core/Classes/Package/PackageManager.php
Expand Up @@ -42,6 +42,11 @@

/**
* The default TYPO3 Package Manager
*
* @phpstan-type PackageKey non-empty-string
* @phpstan-type PackageName non-empty-string
* @phpstan-type PackageConstraints array{dependencies: list<PackageKey>, suggestions: list<PackageKey>}
* @phpstan-type StateConfiguration array{packagePath?: non-empty-string}
*/
class PackageManager implements SingletonInterface
{
Expand All @@ -56,12 +61,12 @@ class PackageManager implements SingletonInterface
protected $packageCache;

/**
* @var array
* @var array{local?: non-empty-string, system?: non-empty-string}
*/
protected $packagesBasePaths = [];

/**
* @var array
* @var array<PackageName, PackageKey>
*/
protected $packageAliasMap = [];

Expand All @@ -73,7 +78,7 @@ class PackageManager implements SingletonInterface

/**
* Array of available packages, indexed by package key
* @var PackageInterface[]
* @var array<PackageKey, PackageInterface>
*/
protected $packages = [];

Expand All @@ -83,14 +88,15 @@ class PackageManager implements SingletonInterface
protected $availablePackagesScanned = false;

/**
* A map between ComposerName and PackageKey, only available when scanAvailablePackages is run
* @var array
* A map between ComposerName and PackageKey, only available when scanAvailablePackages is run,
* e.g. `['typo3/cms-core' => 'core', 'typo3/cms-backend' => 'backend']`
* @var array<PackageName, PackageKey>
*/
protected $composerNameToPackageKeyMap = [];

/**
* List of active packages as package key => package object
* @var array
* @var array<PackageKey, PackageInterface>
*/
protected $activePackages = [];

Expand All @@ -101,7 +107,7 @@ class PackageManager implements SingletonInterface

/**
* Package states configuration as stored in the PackageStates.php file
* @var array
* @var array{packages?: array<PackageKey, StateConfiguration>, version?: int}
*/
protected $packageStatesConfiguration = [];

Expand All @@ -110,10 +116,6 @@ class PackageManager implements SingletonInterface
*/
protected ?string $packagePathMatchRegex;

/**
* @param string|null $packagesBasePath
* @param string|null $packageStatesPathAndFilename
*/
public function __construct(DependencyOrderingService $dependencyOrderingService, string $packageStatesPathAndFilename = null, string $packagesBasePath = null)
{
$this->packagesBasePath = $packagesBasePath ?? Environment::getPublicPath() . '/';
Expand Down Expand Up @@ -354,6 +356,7 @@ protected function scanPackagePathsForExtensions()
/**
* Requires and registers all packages which were defined in packageStatesConfiguration
*
* @param array<PackageKey, StateConfiguration> $packages
* @param bool $registerOnlyNewPackages
* @throws Exception\InvalidPackageStateException
* @throws Exception\PackageStatesFileNotWritableException
Expand Down Expand Up @@ -417,7 +420,7 @@ public function registerPackage(PackageInterface $package)
/**
* Unregisters a package from the list of available packages
*
* @param string $packageKey Package Key of the package to be unregistered
* @param string|PackageKey $packageKey Package Key of the package to be unregistered
*/
protected function unregisterPackageByPackageKey($packageKey)
{
Expand All @@ -443,8 +446,8 @@ static function ($aliasedKey) use ($packageKey) {
/**
* Resolves a TYPO3 package key from a composer package name.
*
* @param string $composerName
* @return string
* @param string|PackageName $composerName
* @return string|PackageKey|PackageName
* @internal
*/
public function getPackageKeyFromComposerName($composerName)
Expand All @@ -462,7 +465,7 @@ public function getPackageKeyFromComposerName($composerName)
* Returns a PackageInterface object for the specified package.
* A package is available, if the package directory contains valid MetaData information.
*
* @param string $packageKey
* @param string|PackageKey $packageKey
* @return PackageInterface The requested package object
* @throws Exception\UnknownPackageException if the specified package is not known
*/
Expand All @@ -478,7 +481,7 @@ public function getPackage($packageKey)
* Returns TRUE if a package is available (the package's files exist in the packages directory)
* or FALSE if it's not. If a package is available it doesn't mean necessarily that it's active!
*
* @param string $packageKey The key of the package to check
* @param string|PackageKey $packageKey The key of the package to check
* @return bool TRUE if the package is available, otherwise FALSE
*/
public function isPackageAvailable($packageKey)
Expand All @@ -499,7 +502,7 @@ public function isPackageAvailable($packageKey)
/**
* Returns TRUE if a package is activated or FALSE if it's not.
*
* @param string $packageKey The key of the package to check
* @param string|PackageKey $packageKey The key of the package to check
* @return bool TRUE if package is active, otherwise FALSE
*/
public function isPackageActive($packageKey)
Expand All @@ -512,7 +515,7 @@ public function isPackageActive($packageKey)
/**
* Deactivates a package and updates the packagestates configuration
*
* @param string $packageKey
* @param string|PackageKey $packageKey
* @throws Exception\PackageStatesFileNotWritableException
* @throws Exception\ProtectedPackageKeyException
* @throws Exception\UnknownPackageException
Expand Down Expand Up @@ -547,7 +550,7 @@ public function deactivatePackage($packageKey)
}

/**
* @param string $packageKey
* @param string|PackageKey $packageKey
* @internal
*/
public function activatePackage($packageKey)
Expand Down Expand Up @@ -577,7 +580,7 @@ protected function registerTransientClassLoadingInformationForPackage(PackageInt
/**
* Removes a package from the file system.
*
* @param string $packageKey
* @param string|PackageKey $packageKey
* @throws Exception
* @throws Exception\ProtectedPackageKeyException
* @throws Exception\UnknownPackageException
Expand Down Expand Up @@ -613,7 +616,7 @@ public function deletePackage($packageKey)
* A package is active, if it is available and has been activated in the package
* manager settings.
*
* @return PackageInterface[]
* @return array<array-key|PackageKey, PackageInterface>
*/
public function getActivePackages()
{
Expand All @@ -630,7 +633,7 @@ public function getActivePackages()
/**
* Returns TRUE if a package was already registered or FALSE if it's not.
*
* @param string $packageKey
* @param string|PackageKey $packageKey
* @return bool
*/
protected function isPackageRegistered($packageKey)
Expand All @@ -645,7 +648,7 @@ protected function isPackageRegistered($packageKey)
* and package configurations arrays holds all packages in the correct
* initialization order.
*
* @return array
* @return array<PackageKey, PackageConstraints>
*/
protected function sortActivePackagesByDependencies()
{
Expand All @@ -668,8 +671,8 @@ protected function sortActivePackagesByDependencies()
* resolved direct or indirect dependencies of each package will put into the package
* states configuration array.
*
* @param array $packageConfig
* @return array
* @param array<PackageKey, mixed> $packageConfig
* @return array<PackageKey, PackageConstraints>
*/
protected function resolvePackageDependencies($packageConfig)
{
Expand All @@ -684,8 +687,8 @@ protected function resolvePackageDependencies($packageConfig)
/**
* Returns an array of suggested package keys for the given package.
*
* @param string $packageKey The package key to fetch the suggestions for
* @return array|null An array of directly suggested packages
* @param string|PackageKey $packageKey The package key to fetch the suggestions for
* @return list<PackageKey>|null An array of directly suggested packages
*/
protected function getSuggestionArrayForPackage($packageKey)
{
Expand Down Expand Up @@ -755,7 +758,7 @@ protected function sortAndSavePackageStates()
/**
* Check the conformance of the given package key
*
* @param string $packageKey The package key to validate
* @param string|PackageKey $packageKey The package key to validate
* @return bool If the package key is valid, returns TRUE otherwise FALSE
*/
public function isPackageKeyValid($packageKey)
Expand All @@ -767,7 +770,7 @@ public function isPackageKeyValid($packageKey)
* Returns an array of \TYPO3\CMS\Core\Package objects of all available packages.
* A package is available, if the package directory contains valid meta information.
*
* @return PackageInterface[] Array of PackageInterface
* @return array<array-key|PackageKey, PackageInterface> Array of PackageInterface
*/
public function getAvailablePackages()
{
Expand Down Expand Up @@ -797,7 +800,7 @@ public function unregisterPackage(PackageInterface $package)
/**
* Reloads a package and its information
*
* @param string $packageKey
* @param string|PackageKey $packageKey
* @throws Exception\InvalidPackageStateException if the package isn't available
* @internal
*/
Expand Down Expand Up @@ -876,7 +879,7 @@ protected function getExtensionEmConf(string $packagePath, string $packageKey):
/**
* Fetches information from ext_emconf.php and maps it so it is treated as it would come from composer.json
*
* @param string $packageKey
* @param string|PackageKey $packageKey
* @return \stdClass
* @throws Exception\InvalidPackageManifestException
*/
Expand Down Expand Up @@ -962,9 +965,9 @@ protected function setComposerManifestValueIfEmpty(\stdClass $manifest, $propert
* do this recursively, so dependencies of dependent packages will also be
* in the result.
*
* @param string $packageKey The package key to fetch the dependencies for
* @param string|PackageKey $packageKey The package key to fetch the dependencies for
* @param array $trace An array of already visited package keys, to detect circular dependencies
* @return array|null An array of direct or indirect dependent packages
* @return list<string>|null An array of direct or indirect dependent packages
* @throws Exception\InvalidPackageKeyException
*/
protected function getDependencyArrayForPackage($packageKey, array &$dependentPackageKeys = [], array $trace = [])
Expand Down Expand Up @@ -1023,7 +1026,7 @@ protected function getPackageKeyFromManifest($manifest, $packagePath)
* The order of paths is crucial for allowing overriding of system extension by local extensions.
* Pay attention if you change order of the paths here.
*
* @return array
* @return array{local?: string, system?: string}
*/
protected function getPackageBasePaths()
{
Expand All @@ -1046,7 +1049,8 @@ protected function hasSubDirectories(string $path): bool
}

/**
* @return array Returns the packageStatesConfiguration sorted by dependencies
* @param array<PackageKey, PackageConstraints> $packageStatesConfiguration
* @return list<PackageKey> Returns the packageStatesConfiguration sorted by dependencies
* @throws \UnexpectedValueException
*/
protected function sortPackageStatesConfigurationByDependency(array $packageStatesConfiguration)
Expand Down Expand Up @@ -1124,9 +1128,9 @@ protected function isComposerDependency(string $packageName): bool
* This ensures that the framework extensions (aka sysext) are
* always loaded first, before any other external extension.
*
* @param array $packageStateConfiguration
* @param array $rootPackageKeys
* @return array
* @param array<PackageKey, PackageConstraints> $packageStateConfiguration
* @param list<PackageKey> $rootPackageKeys
* @return array<PackageKey, PackageConstraints>
*/
protected function addDependencyToFrameworkToAllExtensions(array $packageStateConfiguration, array $rootPackageKeys)
{
Expand Down Expand Up @@ -1154,8 +1158,8 @@ protected function addDependencyToFrameworkToAllExtensions(array $packageStateCo
* This method also introduces dependencies among the dependencies
* to ensure the loading order is exactly as specified in the list.
*
* @param array $packageStateConfiguration
* @return array
* @param array<PackageKey, PackageConstraints> $packageStateConfiguration
* @return array<array-key|PackageKey, array<array-key, bool>>
*/
protected function buildDependencyGraph(array $packageStateConfiguration)
{
Expand All @@ -1168,7 +1172,8 @@ protected function buildDependencyGraph(array $packageStateConfiguration)
}

/**
* @return array
* @param array<PackageKey, PackageConstraints> $packageStateConfiguration
* @return list<PackageKey>
*/
protected function findFrameworkPackages(array $packageStateConfiguration)
{
Expand Down
5 changes: 4 additions & 1 deletion typo3/sysext/core/Classes/Page/ImportMapFactory.php
Expand Up @@ -34,8 +34,11 @@ public function __construct(

public function create(bool $bustSuffix = true): ImportMap
{
$activePackages = array_values(
$this->packageManager->getActivePackages()
);
return new ImportMap(
$this->packageManager->getActivePackages(),
$activePackages,
$this->assetsCache,
$this->cacheIdentifier,
$this->eventDispatcher,
Expand Down
Expand Up @@ -91,7 +91,7 @@ public function orderByDependencies(array $items, $beforeKey = 'before', $afterK
* @param array $dependencies
* @param string $beforeKey The key to use in a dependency which specifies the "before"-relation. eg. 'sortBefore', 'loadBefore'
* @param string $afterKey The key to use in a dependency which specifies the "after"-relation. eg. 'sortAfter', 'loadAfter'
* @return bool[][] The dependency graph
* @return array<array-key, array<array-key, bool>> The dependency graph
*/
public function buildDependencyGraph(array $dependencies, $beforeKey = 'before', $afterKey = 'after')
{
Expand All @@ -100,7 +100,7 @@ public function buildDependencyGraph(array $dependencies, $beforeKey = 'before',
$identifiers = array_keys($dependencies);
sort($identifiers);
// $dependencyGraph is the adjacency matrix as two-dimensional array initialized to FALSE (empty graph)
/** @var bool[][] $dependencyGraph */
/** @var array<array-key, array<array-key, bool>> $dependencyGraph */
$dependencyGraph = array_fill_keys($identifiers, array_fill_keys($identifiers, false));

foreach ($identifiers as $id) {
Expand Down

0 comments on commit 54d22e2

Please sign in to comment.