[TASK] Only show active packages in PackageStates.php 89/46389/20
authorAlexander Stehlik <alexander.stehlik@gmail.com>
Sun, 31 Jan 2016 18:45:23 +0000 (19:45 +0100)
committerHelmut Hummel <helmut.hummel@typo3.org>
Wed, 20 Apr 2016 14:30:23 +0000 (16:30 +0200)
Update the version to 5 and include a list of active packages,
everything else is stored in the core cache, and not needed
to be stored.

Note: the order of the package keys in the DependencyResolver
tests is changed intentionally. The order created by the
DependencyResolver has not changed. The tests did not
detect any difference in the order because we had an
associative array before (now it is indexed where the order
is relevant).

Resolves: #73041
Releases: master
Change-Id: I34e0c89efbef306ce49823069bd9dd4c38fa3091
Reviewed-on: https://review.typo3.org/46389
Reviewed-by: Nicole Cordes <typo3@cordes.co>
Tested-by: Nicole Cordes <typo3@cordes.co>
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Tested-by: Helmut Hummel <helmut.hummel@typo3.org>
typo3/sysext/core/Classes/Package/DependencyResolver.php
typo3/sysext/core/Classes/Package/FailsafePackageManager.php
typo3/sysext/core/Classes/Package/PackageManager.php
typo3/sysext/core/Classes/Package/UnitTestPackageManager.php
typo3/sysext/core/Documentation/Changelog/master/Important-73041-PackageStatesIncludesOnlyActivePackages.rst [new file with mode: 0644]
typo3/sysext/core/Tests/Testbase.php
typo3/sysext/core/Tests/Unit/Package/DependencyResolverTest.php
typo3/sysext/core/Tests/Unit/Package/PackageManagerTest.php

index fec6194..9df659c 100644 (file)
@@ -25,11 +25,6 @@ use TYPO3\CMS\Core\Service\DependencyOrderingService;
 class DependencyResolver
 {
     /**
-     * Folder with framework extensions
-     */
-    const SYSEXT_FOLDER = 'typo3/sysext';
-
-    /**
      * @var DependencyOrderingService
      */
     protected $dependencyOrderingService;
@@ -49,24 +44,7 @@ class DependencyResolver
      */
     public function sortPackageStatesConfigurationByDependency(array $packageStatesConfiguration)
     {
-        // We just want to consider active packages
-        $activePackageStatesConfiguration = array_filter($packageStatesConfiguration, function ($packageState) {
-            return isset($packageState['state']) && $packageState['state'] === 'active';
-        });
-        $inactivePackageStatesConfiguration = array_diff_key($packageStatesConfiguration, $activePackageStatesConfiguration);
-
-        $sortedPackageKeys = $this->dependencyOrderingService->calculateOrder($this->buildDependencyGraph($activePackageStatesConfiguration));
-
-        // Reorder the package states according to the loading order
-        $newPackageStatesConfiguration = array();
-        foreach ($sortedPackageKeys as $packageKey) {
-            $newPackageStatesConfiguration[$packageKey] = $packageStatesConfiguration[$packageKey];
-        }
-
-        // Append the inactive configurations again
-        $newPackageStatesConfiguration = array_merge($newPackageStatesConfiguration, $inactivePackageStatesConfiguration);
-
-        return $newPackageStatesConfiguration;
+        return $this->dependencyOrderingService->calculateOrder($this->buildDependencyGraph($packageStatesConfiguration));
     }
 
     /**
index 1c06feb..91dc777 100644 (file)
@@ -22,25 +22,11 @@ namespace TYPO3\CMS\Core\Package;
 class FailsafePackageManager extends PackageManager
 {
     /**
-     * @var \TYPO3\CMS\Core\Configuration\ConfigurationManager
-     */
-    protected $configurationManager;
-
-    /**
      * @var bool TRUE if package manager is in failsafe mode
      */
     protected $inFailsafeMode = false;
 
     /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        $this->configurationManager = new \TYPO3\CMS\Core\Configuration\ConfigurationManager;
-        parent::__construct();
-    }
-
-    /**
      * Loads the states of available packages from the PackageStates.php file.
      * The result is stored in $this->packageStatesConfiguration.
      *
@@ -58,17 +44,6 @@ class FailsafePackageManager extends PackageManager
     }
 
     /**
-     * Requires and registers all packages which were defined in packageStatesConfiguration
-     *
-     * @return void
-     */
-    protected function registerPackagesFromConfiguration($registerOnlyNewPackages = false)
-    {
-        $this->packageStatesConfiguration['packages']['install']['state'] = 'active';
-        parent::registerPackagesFromConfiguration($registerOnlyNewPackages);
-    }
-
-    /**
      * Sort and save states
      *
      * @return void
index 3658c57..15d3d4d 100644 (file)
@@ -83,7 +83,7 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
      * List of active packages as package key => package object
      * @var array
      */
-    protected $activePackages = array();
+    protected $activePackages = [];
 
     /**
      * @var string
@@ -175,7 +175,6 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
             $packageCache = array(
                 'packageStatesConfiguration' => $this->packageStatesConfiguration,
                 'packageAliasMap' => $this->packageAliasMap,
-                'activePackageKeys' => array_keys($this->activePackages),
                 'loadedExtArray' => $GLOBALS['TYPO3_LOADED_EXT'],
                 'composerNameToPackageKeyMap' => $this->composerNameToPackageKeyMap,
                 'packageObjectsCacheEntryIdentifier' => $packageObjectsCacheEntryIdentifier
@@ -200,6 +199,9 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
             throw new Exception\PackageManagerCacheUnavailableException('The package state cache could not be loaded.', 1393883342);
         }
         $this->packageStatesConfiguration = $packageCache['packageStatesConfiguration'];
+        if ($this->packageStatesConfiguration['version'] < 5) {
+            throw new Exception\PackageManagerCacheUnavailableException('The package state cache could not be loaded.', 1393883341);
+        }
         $this->packageAliasMap = $packageCache['packageAliasMap'];
         $this->composerNameToPackageKeyMap = $packageCache['composerNameToPackageKeyMap'];
         $GLOBALS['TYPO3_LOADED_EXT'] = $packageCache['loadedExtArray'];
@@ -207,9 +209,6 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
         // Strip off PHP Tags from Php Cache Frontend
         $packageObjects = substr(substr($this->coreCache->get($packageCache['packageObjectsCacheEntryIdentifier']), 6), 0, -2);
         $this->packages = unserialize($packageObjects);
-        foreach ($packageCache['activePackageKeys'] as $activePackageKey) {
-            $this->activePackages[$activePackageKey] = $this->packages[$activePackageKey];
-        }
         unset($GLOBALS['TYPO3_currentPackageManager']);
     }
 
@@ -222,12 +221,26 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
      */
     protected function loadPackageStates()
     {
+        $forcePackageStatesRewrite = false;
         $this->packageStatesConfiguration = @include($this->packageStatesPathAndFilename) ?: array();
         if (!isset($this->packageStatesConfiguration['version']) || $this->packageStatesConfiguration['version'] < 4) {
             $this->packageStatesConfiguration = array();
+        } elseif ($this->packageStatesConfiguration['version'] === 4) {
+            // Convert to v5 format which only includes a list of active packages.
+            // Deprecated since version 8, will be removed in version 9.
+            $activePackages = [];
+            foreach ($this->packageStatesConfiguration['packages'] as $packageKey => $packageConfiguration) {
+                if ($packageConfiguration['state'] !== 'active') {
+                    continue;
+                }
+                $activePackages[$packageKey] = ['packagePath' => $packageConfiguration['packagePath']];
+            }
+            $this->packageStatesConfiguration['packages'] = $activePackages;
+            $this->packageStatesConfiguration['version'] = 5;
+            $forcePackageStatesRewrite = true;
         }
         if ($this->packageStatesConfiguration !== array()) {
-            $this->registerPackagesFromConfiguration();
+            $this->registerPackagesFromConfiguration($this->packageStatesConfiguration['packages'], false, $forcePackageStatesRewrite);
         } else {
             throw new Exception\PackageStatesUnavailableException('The PackageStates.php file is either corrupt or unavailable.', 1381507733);
         }
@@ -242,27 +255,37 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
      */
     protected function initializePackageObjects()
     {
-        $requiredPackages = array();
+        $requiredPackages = [];
+        $activePackages = [];
         foreach ($this->packages as $packageKey => $package) {
             if ($package->isProtected()) {
                 $requiredPackages[$packageKey] = $package;
             }
-            if (isset($this->packageStatesConfiguration['packages'][$packageKey]['state']) && $this->packageStatesConfiguration['packages'][$packageKey]['state'] === 'active') {
-                $this->activePackages[$packageKey] = $package;
+            if (isset($this->packageStatesConfiguration['packages'][$packageKey])) {
+                $activePackages[$packageKey] = $package;
             }
         }
-        $previousActivePackages = $this->activePackages;
-        $this->activePackages = array_merge($requiredPackages, $this->activePackages);
+        $previousActivePackages = $activePackages;
+        $activePackages = array_merge($requiredPackages, $activePackages);
 
-        if ($this->activePackages != $previousActivePackages) {
+        if ($activePackages != $previousActivePackages) {
             foreach ($requiredPackages as $requiredPackageKey => $package) {
-                $this->packageStatesConfiguration['packages'][$requiredPackageKey]['state'] = 'active';
+                $this->registerActivePackage($package);
             }
             $this->sortAndSavePackageStates();
         }
     }
 
     /**
+     * @param PackageInterface $package
+     */
+    protected function registerActivePackage(PackageInterface $package) {
+        // reset the active packages so they are rebuilt.
+        $this->activePackages = [];
+        $this->packageStatesConfiguration['packages'][$package->getPackageKey()] = ['packagePath' => str_replace($this->packagesBasePath, '',  $package->getPackagePath())];
+    }
+
+    /**
      * Initializes a backwards compatibility $GLOBALS['TYPO3_LOADED_EXT'] array
      *
      * @return void
@@ -281,24 +304,14 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
      */
     public function scanAvailablePackages()
     {
-        $previousPackageStatesConfiguration = $this->packageStatesConfiguration;
-
-        if (isset($this->packageStatesConfiguration['packages'])) {
-            foreach ($this->packageStatesConfiguration['packages'] as $packageKey => $configuration) {
-                if (!@file_exists($this->packagesBasePath . $configuration['packagePath'])) {
-                    unset($this->packageStatesConfiguration['packages'][$packageKey]);
-                }
-            }
-        } else {
-            $this->packageStatesConfiguration['packages'] = array();
-        }
-
         $packagePaths = $this->scanPackagePathsForExtensions();
+        $packages = [];
         foreach ($packagePaths as $packageKey => $packagePath) {
             try {
                 $composerManifest = $this->getComposerManifest($packagePath);
                 $packageKey = $this->getPackageKeyFromManifest($composerManifest, $packagePath);
                 $this->composerNameToPackageKeyMap[strtolower($composerManifest->name)] = $packageKey;
+                $packages[$packageKey] = ['packagePath' => str_replace($this->packagesBasePath, '', $packagePath)];
             } catch (Exception\MissingPackageManifestException $exception) {
                 if (!$this->isPackageKeyValid($packageKey)) {
                     continue;
@@ -306,18 +319,29 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
             } catch (Exception\InvalidPackageKeyException $exception) {
                 continue;
             }
-            if (!isset($this->packageStatesConfiguration['packages'][$packageKey]['state'])) {
-                $this->packageStatesConfiguration['packages'][$packageKey]['state'] = 'inactive';
-            }
-
-            $this->packageStatesConfiguration['packages'][$packageKey]['packagePath'] = str_replace($this->packagesBasePath, '', $packagePath);
         }
 
         $registerOnlyNewPackages = !empty($this->packages);
-        $this->registerPackagesFromConfiguration($registerOnlyNewPackages);
-        if ($this->packageStatesConfiguration != $previousPackageStatesConfiguration) {
-            $this->sortAndSavePackageStates();
-        }
+        $this->registerPackagesFromConfiguration($packages, $registerOnlyNewPackages);
+    }
+
+    /**
+     * Scans all directories for a certain package.
+     *
+     * @param string $packageKey
+     * @return PackageInterface
+     */
+    protected function registerPackageDuringRuntime($packageKey)
+    {
+        $packagePaths = $this->scanPackagePathsForExtensions();
+        $packagePath = $packagePaths[$packageKey];
+        $composerManifest = $this->getComposerManifest($packagePath);
+        $packageKey = $this->getPackageKeyFromManifest($composerManifest, $packagePath);
+        $this->composerNameToPackageKeyMap[strtolower($composerManifest->name)] = $packageKey;
+        $packagePath = PathUtility::sanitizeTrailingSeparator($packagePath);
+        $package = new Package($this, $packageKey, $packagePath);
+        $this->registerPackage($package);
+        return $package;
     }
 
     /**
@@ -358,13 +382,15 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
     /**
      * Requires and registers all packages which were defined in packageStatesConfiguration
      *
+     * @param array $packages
      * @param bool $registerOnlyNewPackages
-     * @return void
+     * @param bool $packageStatesHasChanged
+     * @throws Exception\InvalidPackageStateException
+     * @throws Exception\PackageStatesFileNotWritableException
      */
-    protected function registerPackagesFromConfiguration($registerOnlyNewPackages = false)
+    protected function registerPackagesFromConfiguration(array $packages, $registerOnlyNewPackages = false, $packageStatesHasChanged = false)
     {
-        $packageStatesHasChanged = false;
-        foreach ($this->packageStatesConfiguration['packages'] as $packageKey => $stateConfiguration) {
+        foreach ($packages as $packageKey => $stateConfiguration) {
             if ($registerOnlyNewPackages && $this->isPackageAvailable($packageKey)) {
                 continue;
             }
@@ -392,11 +418,7 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
                 continue;
             }
 
-            $this->registerPackage($package, false);
-
-            if ($stateConfiguration['state'] === 'active') {
-                $this->activePackages[$packageKey] = $this->packages[$packageKey];
-            }
+            $this->registerPackage($package);
         }
         if ($packageStatesHasChanged) {
             $this->sortAndSavePackageStates();
@@ -407,12 +429,11 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
      * Register a native TYPO3 package
      *
      * @param PackageInterface $package The Package to be registered
-     * @param bool $sortAndSave allows for not saving packagestates when used in loops etc.
      * @return PackageInterface
      * @throws Exception\InvalidPackageStateException
      * @throws Exception\PackageStatesFileNotWritableException
      */
-    public function registerPackage(PackageInterface $package, $sortAndSave = true)
+    public function registerPackage(PackageInterface $package)
     {
         $packageKey = $package->getPackageKey();
         if ($this->isPackageAvailable($packageKey)) {
@@ -420,11 +441,6 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
         }
 
         $this->packages[$packageKey] = $package;
-        $this->packageStatesConfiguration['packages'][$packageKey]['packagePath'] = str_replace($this->packagesBasePath, '', $package->getPackagePath());
-
-        if ($sortAndSave === true) {
-            $this->sortAndSavePackageStates();
-        }
 
         if ($package instanceof PackageInterface) {
             foreach ($package->getPackageReplacementKeys() as $packageToReplace => $versionConstraint) {
@@ -519,7 +535,7 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
      */
     public function isPackageActive($packageKey)
     {
-        return isset($this->runtimeActivatedPackages[$packageKey]) || isset($this->activePackages[$packageKey]);
+        return isset($this->runtimeActivatedPackages[$packageKey]) || isset($this->packageStatesConfiguration['packages'][$packageKey]);
     }
 
     /**
@@ -532,10 +548,10 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
      */
     public function deactivatePackage($packageKey)
     {
-        $this->sortAvailablePackagesByDependencies();
+        $packagesWithDependencies = $this->sortActivePackagesByDependencies();
 
-        foreach ($this->packageStatesConfiguration['packages'] as $packageStateKey => $packageStateConfiguration) {
-            if ($packageKey === $packageStateKey || empty($packageStateConfiguration['dependencies']) || $packageStateConfiguration['state'] !== 'active') {
+        foreach ($packagesWithDependencies as $packageStateKey => $packageStateConfiguration) {
+            if ($packageKey === $packageStateKey || empty($packageStateConfiguration['dependencies'])) {
                 continue;
             }
             if (in_array($packageKey, $packageStateConfiguration['dependencies'], true)) {
@@ -552,8 +568,8 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
             throw new Exception\ProtectedPackageKeyException('The package "' . $packageKey . '" is protected and cannot be deactivated.', 1308662891);
         }
 
-        unset($this->activePackages[$packageKey]);
-        $this->packageStatesConfiguration['packages'][$packageKey]['state'] = 'inactive';
+        $this->activePackages = [];
+        unset($this->packageStatesConfiguration['packages'][$packageKey]);
         $this->sortAndSavePackageStates();
     }
 
@@ -569,11 +585,7 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
             return;
         }
 
-        $this->activePackages[$packageKey] = $package;
-        $this->packageStatesConfiguration['packages'][$packageKey]['state'] = 'active';
-        if (!isset($this->packageStatesConfiguration['packages'][$packageKey]['packagePath'])) {
-            $this->packageStatesConfiguration['packages'][$packageKey]['packagePath'] = str_replace($this->packagesBasePath, '', $package->getPackagePath());
-        }
+        $this->registerActivePackage($package);
         $this->sortAndSavePackageStates();
     }
 
@@ -585,7 +597,7 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
      */
     public function activatePackageDuringRuntime($packageKey)
     {
-        $package = $this->getPackage($packageKey);
+        $package = $this->registerPackageDuringRuntime($packageKey);
         $this->runtimeActivatedPackages[$package->getPackageKey()] = $package;
         if (!isset($GLOBALS['TYPO3_LOADED_EXT'][$package->getPackageKey()])) {
             $loadedExtArrayElement = new LoadedExtensionArrayElement($package);
@@ -650,30 +662,40 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
      */
     public function getActivePackages()
     {
+        if (empty($this->activePackages)) {
+            if (!empty($this->packageStatesConfiguration['packages'])) {
+                foreach ($this->packageStatesConfiguration['packages'] as $packageKey => $packageConfig) {
+                    $this->activePackages[$packageKey] = $this->getPackage($packageKey);
+                }
+            }
+        }
         return array_merge($this->activePackages, $this->runtimeActivatedPackages);
     }
 
     /**
-     * Orders all packages by comparing their dependencies. By this, the packages
+     * Orders all active packages by comparing their dependencies. By this, the packages
      * and package configurations arrays holds all packages in the correct
      * initialization order.
      *
-     * @return void
+     * @return array
      */
-    protected function sortAvailablePackagesByDependencies()
+    protected function sortActivePackagesByDependencies()
     {
-        $this->resolvePackageDependencies();
+        $packagesWithDependencies = $this->resolvePackageDependencies($this->packageStatesConfiguration['packages']);
 
         // sort the packages by key at first, so we get a stable sorting of "equivalent" packages afterwards
-        ksort($this->packageStatesConfiguration['packages']);
-        $this->packageStatesConfiguration['packages'] = $this->dependencyResolver->sortPackageStatesConfigurationByDependency($this->packageStatesConfiguration['packages']);
+        ksort($packagesWithDependencies);
+        $sortedPackageKeys = $this->dependencyResolver->sortPackageStatesConfigurationByDependency($packagesWithDependencies);
 
         // Reorder the packages according to the loading order
         $newPackages = array();
-        foreach ($this->packageStatesConfiguration['packages'] as $packageKey => $_) {
+        $this->packageStatesConfiguration['packages'] = [];
+        foreach ($sortedPackageKeys as $packageKey) {
             $newPackages[$packageKey] = $this->packages[$packageKey];
+            $this->registerActivePackage($this->packages[$packageKey]);
         }
         $this->packages = $newPackages;
+        return $packagesWithDependencies;
     }
 
     /**
@@ -681,16 +703,17 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
      * resolved direct or indirect dependencies of each package will put into the package
      * states configuration array.
      *
-     * @return void
+     * @param $packageConfig
+     * @return array
      */
-    protected function resolvePackageDependencies()
+    protected function resolvePackageDependencies($packageConfig)
     {
-        foreach ($this->packages as $packageKey => $package) {
-            $this->packageStatesConfiguration['packages'][$packageKey]['dependencies'] = $this->getDependencyArrayForPackage($packageKey);
-        }
-        foreach ($this->packages as $packageKey => $package) {
-            $this->packageStatesConfiguration['packages'][$packageKey]['suggestions'] = $this->getSuggestionArrayForPackage($packageKey);
+        $packagesWithDependencies = [];
+        foreach ($packageConfig as $packageKey => $_) {
+            $packagesWithDependencies[$packageKey]['dependencies'] = $this->getDependencyArrayForPackage($packageKey);
+            $packagesWithDependencies[$packageKey]['suggestions'] = $this->getSuggestionArrayForPackage($packageKey);
         }
+        return $packagesWithDependencies;
     }
 
     /**
@@ -725,9 +748,9 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
      */
     protected function sortAndSavePackageStates()
     {
-        $this->sortAvailablePackagesByDependencies();
+        $this->sortActivePackagesByDependencies();
 
-        $this->packageStatesConfiguration['version'] = 4;
+        $this->packageStatesConfiguration['version'] = 5;
 
         $fileDescription = "# PackageStates.php\n\n";
         $fileDescription .= "# This file is maintained by TYPO3's package management. Although you can edit it\n";
@@ -735,15 +758,6 @@ class PackageManager implements \TYPO3\CMS\Core\SingletonInterface
         $fileDescription .= "# This file will be regenerated automatically if it doesn't exist. Deleting this file\n";
         $fileDescription .= "# should, however, never become necessary if you use the package commands.\n";
 
-        // We do not need the dependencies and suggestions on disk...
-        foreach ($this->packageStatesConfiguration['packages'] as &$packageConfiguration) {
-            if (isset($packageConfiguration['dependencies'])) {
-                unset($packageConfiguration['dependencies']);
-            }
-            if (isset($packageConfiguration['suggestions'])) {
-                unset($packageConfiguration['suggestions']);
-            }
-        }
         if (!@is_writable($this->packageStatesPathAndFilename)) {
             // If file does not exists try to create it
             $fileHandle = @fopen($this->packageStatesPathAndFilename, 'x');
index 3f95c6f..ac93de4 100644 (file)
@@ -30,7 +30,9 @@ class UnitTestPackageManager extends PackageManager
     public function initialize()
     {
         $this->scanAvailablePackages();
-        $this->activePackages = $this->packages;
+        foreach ($this->packages as $package) {
+            $this->registerActivePackage($package);
+        }
     }
 
     /**
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Important-73041-PackageStatesIncludesOnlyActivePackages.rst b/typo3/sysext/core/Documentation/Changelog/master/Important-73041-PackageStatesIncludesOnlyActivePackages.rst
new file mode 100644 (file)
index 0000000..7d619fb
--- /dev/null
@@ -0,0 +1,9 @@
+===============================================================
+Important: #73041 - PackageStates Includes Only Active Packages
+===============================================================
+
+Description
+===========
+
+The information about the packages available in the system located in typo3conf/PackageStates.php was
+thinned out to only include the extension keys of the active (= installed) extensions.
\ No newline at end of file
index 4e77f6a..199c478 100644 (file)
@@ -429,46 +429,28 @@ class Testbase
     ) {
         $packageStates = array(
             'packages' => array(),
-            'version' => 4,
+            'version' => 5,
         );
 
         // Register default list of extensions and set active
         foreach ($defaultCoreExtensionsToLoad as $extensionName) {
             $packageStates['packages'][$extensionName] = array(
-                'state' => 'active',
-                'packagePath' => 'typo3/sysext/' . $extensionName . '/',
-                'classesPath' => 'Classes/',
+                'packagePath' => 'typo3/sysext/' . $extensionName . '/'
             );
         }
 
         // Register additional core extensions and set active
         foreach ($additionalCoreExtensionsToLoad as $extensionName) {
-            if (isset($packageSates['packages'][$extensionName])) {
-                throw new Exception(
-                    $extensionName . ' is already registered as default core extension to load, no need to load it explicitly',
-                    1390913893
-                );
-            }
             $packageStates['packages'][$extensionName] = array(
-                'state' => 'active',
-                'packagePath' => 'typo3/sysext/' . $extensionName . '/',
-                'classesPath' => 'Classes/',
+                'packagePath' => 'typo3/sysext/' . $extensionName . '/'
             );
         }
 
         // Activate test extensions that have been symlinked before
         foreach ($testExtensionPaths as $extensionPath) {
             $extensionName = basename($extensionPath);
-            if (isset($packageSates['packages'][$extensionName])) {
-                throw new Exception(
-                    $extensionName . ' is already registered as extension to load, no need to load it explicitly',
-                    1390913894
-                );
-            }
             $packageStates['packages'][$extensionName] = array(
-                'state' => 'active',
-                'packagePath' => 'typo3conf/ext/' . $extensionName . '/',
-                'classesPath' => 'Classes/',
+                'packagePath' => 'typo3conf/ext/' . $extensionName . '/'
             );
         }
 
index 8f564c1..c33bf27 100644 (file)
@@ -48,15 +48,15 @@ class DependencyResolverTest extends UnitTestCase
      * @param array $frameworkPackageKeys
      * @param array $expectedSortedPackageStatesConfiguration
      */
-    public function sortPackageStatesConfigurationByDependencyMakesSureThatDependantPackagesAreStandingBeforeAPackageInTheInternalPackagesAndPackagesConfigurationArrays($unsortedPackageStatesConfiguration, $frameworkPackageKeys, $expectedSortedPackageStatesConfiguration)
+    public function sortPackageStatesConfigurationByDependencyMakesSureThatDependantPackagesAreStandingBeforeAPackageInTheInternalPackagesAndPackagesConfigurationArrays($unsortedPackageStatesConfiguration, $frameworkPackageKeys, $expectedSortedPackageKeys)
     {
         /** @var DependencyResolver|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $dependencyResolver */
         $dependencyResolver = $this->getAccessibleMock(DependencyResolver::class, array('findFrameworkPackages'));
         $dependencyResolver->injectDependencyOrderingService(new DependencyOrderingService());
         $dependencyResolver->expects($this->any())->method('findFrameworkPackages')->willReturn($frameworkPackageKeys);
-        $sortedPackageStatesConfiguration = $dependencyResolver->_call('sortPackageStatesConfigurationByDependency', $unsortedPackageStatesConfiguration);
+        $sortedPackageKeys = $dependencyResolver->_call('sortPackageStatesConfigurationByDependency', $unsortedPackageStatesConfiguration);
 
-        $this->assertEquals($expectedSortedPackageStatesConfiguration, $sortedPackageStatesConfiguration, 'The package states configurations have not been ordered according to their dependencies!');
+        $this->assertEquals($expectedSortedPackageKeys, $sortedPackageKeys, 'The package states configurations have not been ordered according to their dependencies!');
     }
 
     /**
@@ -67,11 +67,9 @@ class DependencyResolverTest extends UnitTestCase
     {
         $unsortedPackageStatesConfiguration = array(
             'A' => array(
-                'state' => 'active',
                 'dependencies' => array('B'),
             ),
             'B' => array(
-                'state' => 'active',
                 'dependencies' => array('A')
             ),
         );
@@ -92,23 +90,18 @@ class DependencyResolverTest extends UnitTestCase
             'TYPO3 Flow Packages' => array(
                 array(
                     'TYPO3.Flow' => array(
-                        'state' => 'active',
                         'dependencies' => array('Symfony.Component.Yaml', 'Doctrine.Common', 'Doctrine.DBAL', 'Doctrine.ORM')
                     ),
                     'Doctrine.ORM' => array(
-                        'state' => 'active',
                         'dependencies' => array('Doctrine.Common', 'Doctrine.DBAL')
                     ),
                     'Doctrine.Common' => array(
-                        'state' => 'active',
                         'dependencies' => array()
                     ),
                     'Doctrine.DBAL' => array(
-                        'state' => 'active',
                         'dependencies' => array('Doctrine.Common')
                     ),
                     'Symfony.Component.Yaml' => array(
-                        'state' => 'active',
                         'dependencies' => array()
                     ),
                 ),
@@ -156,31 +149,24 @@ class DependencyResolverTest extends UnitTestCase
             'TYPO3 CMS Extensions' => array(
                 array(
                     'core' => array(
-                        'state' => 'active',
                         'dependencies' => array(),
                     ),
                     'setup' => array(
-                        'state' => 'active',
                         'dependencies' => array('core'),
                     ),
                     'openid' => array(
-                        'state' => 'active',
                         'dependencies' => array('core', 'setup')
                     ),
                     'news' => array(
-                        'state' => 'active',
                         'dependencies' => array('extbase'),
                     ),
                     'extbase' => array(
-                        'state' => 'active',
                         'dependencies' => array('core'),
                     ),
                     'pt_extbase' => array(
-                        'state' => 'active',
                         'dependencies' => array('extbase'),
                     ),
                     'foo' => array(
-                        'state' => 'active',
                         'dependencies' => array(),
                     ),
                 ),
@@ -256,27 +242,21 @@ class DependencyResolverTest extends UnitTestCase
             'Dummy Packages' => array(
                 array(
                     'A' => array(
-                        'state' => 'active',
                         'dependencies' => array('B', 'D', 'C'),
                     ),
                     'B' => array(
-                        'state' => 'active',
                         'dependencies' => array()
                     ),
                     'C' => array(
-                        'state' => 'active',
                         'dependencies' => array('E')
                     ),
                     'D' => array(
-                        'state' => 'active',
                         'dependencies' => array('E'),
                     ),
                     'E' => array(
-                        'state' => 'active',
                         'dependencies' => array(),
                     ),
                     'F' => array(
-                        'state' => 'active',
                         'dependencies' => array(),
                     ),
                 ),
@@ -346,23 +326,18 @@ class DependencyResolverTest extends UnitTestCase
             'TYPO3 Flow Packages' => array(
                 array(
                     'TYPO3.Flow' => array(
-                        'state' => 'active',
                         'dependencies' => array('Symfony.Component.Yaml', 'Doctrine.Common', 'Doctrine.DBAL', 'Doctrine.ORM')
                     ),
                     'Doctrine.ORM' => array(
-                        'state' => 'active',
                         'dependencies' => array('Doctrine.Common', 'Doctrine.DBAL')
                     ),
                     'Doctrine.Common' => array(
-                        'state' => 'active',
                         'dependencies' => array()
                     ),
                     'Doctrine.DBAL' => array(
-                        'state' => 'active',
                         'dependencies' => array('Doctrine.Common')
                     ),
                     'Symfony.Component.Yaml' => array(
-                        'state' => 'active',
                         'dependencies' => array()
                     ),
                 ),
@@ -370,56 +345,34 @@ class DependencyResolverTest extends UnitTestCase
                     'Doctrine.Common'
                 ),
                 array(
-                    'Doctrine.Common' => array(
-                        'state' => 'active',
-                        'dependencies' => array()
-                    ),
-                    'Doctrine.DBAL' => array(
-                        'state' => 'active',
-                        'dependencies' => array('Doctrine.Common')
-                    ),
-                    'Doctrine.ORM' => array(
-                        'state' => 'active',
-                        'dependencies' => array('Doctrine.Common', 'Doctrine.DBAL')
-                    ),
-                    'Symfony.Component.Yaml' => array(
-                        'state' => 'active',
-                        'dependencies' => array()
-                    ),
-                    'TYPO3.Flow' => array(
-                        'state' => 'active',
-                        'dependencies' => array('Symfony.Component.Yaml', 'Doctrine.Common', 'Doctrine.DBAL', 'Doctrine.ORM')
-                    ),
+                    'Doctrine.Common',
+                    'Doctrine.DBAL',
+                    'Doctrine.ORM',
+                    'Symfony.Component.Yaml',
+                    'TYPO3.Flow',
                 ),
             ),
             'TYPO3 CMS Extensions' => array(
                 array(
                     'core' => array(
-                        'state' => 'active',
                         'dependencies' => array(),
                     ),
                     'setup' => array(
-                        'state' => 'active',
                         'dependencies' => array('core'),
                     ),
                     'openid' => array(
-                        'state' => 'active',
                         'dependencies' => array('core', 'setup')
                     ),
                     'news' => array(
-                        'state' => 'active',
                         'dependencies' => array('extbase'),
                     ),
                     'extbase' => array(
-                        'state' => 'active',
                         'dependencies' => array('core'),
                     ),
                     'pt_extbase' => array(
-                        'state' => 'active',
                         'dependencies' => array('extbase'),
                     ),
                     'foo' => array(
-                        'state' => 'active',
                         'dependencies' => array(),
                     ),
                 ),
@@ -427,60 +380,33 @@ class DependencyResolverTest extends UnitTestCase
                     'core', 'setup', 'openid', 'extbase'
                 ),
                 array(
-                    'core' => array(
-                        'state' => 'active',
-                        'dependencies' => array(),
-                    ),
-                    'setup' => array(
-                        'state' => 'active',
-                        'dependencies' => array('core'),
-                    ),
-                    'openid' => array(
-                        'state' => 'active',
-                        'dependencies' => array('core', 'setup')
-                    ),
-                    'extbase' => array(
-                        'state' => 'active',
-                        'dependencies' => array('core'),
-                    ),
-                    'foo' => array(
-                        'state' => 'active',
-                        'dependencies' => array(),
-                    ),
-                    'pt_extbase' => array(
-                        'state' => 'active',
-                        'dependencies' => array('extbase'),
-                    ),
-                    'news' => array(
-                        'state' => 'active',
-                        'dependencies' => array('extbase'),
-                    ),
+                    'core',
+                    'setup',
+                    'openid',
+                    'extbase',
+                    'foo',
+                    'news',
+                    'pt_extbase',
                 ),
             ),
             'Dummy Packages' => array(
                 array(
                     'A' => array(
-                        'state' => 'active',
                         'dependencies' => array('B', 'D', 'C'),
                     ),
                     'B' => array(
-                        'state' => 'active',
                         'dependencies' => array()
                     ),
                     'C' => array(
-                        'state' => 'active',
                         'dependencies' => array('E')
                     ),
                     'D' => array(
-                        'state' => 'active',
                         'dependencies' => array('E'),
                     ),
                     'E' => array(
-                        'state' => 'active',
                         'dependencies' => array(),
                     ),
                     'F' => array(
-                        'state' => 'active',
                         'dependencies' => array(),
                     ),
                 ),
@@ -488,30 +414,12 @@ class DependencyResolverTest extends UnitTestCase
                     'B', 'C', 'E'
                 ),
                 array(
-                    'B' => array(
-                        'state' => 'active',
-                        'dependencies' => array(),
-                    ),
-                    'E' => array(
-                        'state' => 'active',
-                        'dependencies' => array(),
-                    ),
-                    'C' => array(
-                        'state' => 'active',
-                        'dependencies' => array('E'),
-                    ),
-                    'F' => array(
-                        'state' => 'active',
-                        'dependencies' => array(),
-                    ),
-                    'D' => array(
-                        'state' => 'active',
-                        'dependencies' => array('E'),
-                    ),
-                    'A' => array(
-                        'state' => 'active',
-                        'dependencies' => array('B', 'D', 'C'),
-                    ),
+                    'E',
+                    'C',
+                    'B',
+                    'D',
+                    'A',
+                    'F',
                 ),
             ),
         );
index af88d02..1af88a5 100644 (file)
@@ -25,7 +25,7 @@ use TYPO3\CMS\Core\Package\PackageManager;
 class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
 {
     /**
-     * @var PackageManager
+     * @var PackageManager|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $packageManager
      */
     protected $packageManager;
 
@@ -44,11 +44,11 @@ class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
         $mockCache->expects($this->any())->method('set')->will($this->returnValue(true));
         $mockCache->expects($this->any())->method('getBackend')->will($this->returnValue($mockCacheBackend));
         $mockCacheBackend->expects($this->any())->method('getCacheDirectory')->will($this->returnValue('vfs://Test/Cache'));
-        $this->packageManager = $this->getAccessibleMock(PackageManager::class, array('sortAndSavePackageStates', 'sortAvailablePackagesByDependencies', 'registerTransientClassLoadingInformationForPackage'));
+        $this->packageManager = $this->getAccessibleMock(PackageManager::class, array('sortAndSavePackageStates', 'sortActivePackagesByDependencies', 'registerTransientClassLoadingInformationForPackage'));
 
         mkdir('vfs://Test/Packages/Application', 0700, true);
         mkdir('vfs://Test/Configuration');
-        file_put_contents('vfs://Test/Configuration/PackageStates.php', "<?php return array ('packages' => array(), 'version' => 4); ");
+        file_put_contents('vfs://Test/Configuration/PackageStates.php', "<?php return array ('packages' => array(), 'version' => 5); ");
 
         $composerNameToPackageKeyMap = array(
             'typo3/flow' => 'TYPO3.Flow'
@@ -140,8 +140,10 @@ class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
             $this->getUniqueId('Lolli.Pop.NothingElse')
         );
 
+        $packagePaths = [];
         foreach ($expectedPackageKeys as $packageKey) {
             $packagePath = 'vfs://Test/Packages/Application/' . $packageKey . '/';
+            $packagePaths[] = $packagePath;
 
             mkdir($packagePath, 0770, true);
             file_put_contents($packagePath . 'composer.json', '{"name": "' . $packageKey . '", "type": "typo3-cms-test"}');
@@ -150,7 +152,7 @@ class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
 
         /** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $packageManager */
         $packageManager = $this->getAccessibleMock(PackageManager::class, array('dummy'));
-        $packageManager->_set('packagesBasePaths', array('local' => 'vfs://Test/Packages/Application'));
+        $packageManager->_set('packagesBasePaths', $packagePaths);
         $packageManager->_set('packagesBasePath', 'vfs://Test/Packages/');
         $packageManager->_set('packageStatesPathAndFilename', 'vfs://Test/Configuration/PackageStates.php');
 
@@ -159,7 +161,7 @@ class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
         $dependencyResolver
             ->expects($this->any())
             ->method('sortPackageStatesConfigurationByDependency')
-            ->willReturnArgument(0);
+            ->willReturnCallback('array_keys');
 
         $packageManager->injectDependencyResolver($dependencyResolver);
 
@@ -167,17 +169,16 @@ class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
         $packageManager->_set('packageStatesConfiguration', array(
             'packages' => array(
                 $packageKey => array(
-                    'state' => 'inactive',
                     'packagePath' => 'Application/' . $packageKey . '/'
                 )
             ),
-            'version' => 4
+            'version' => 5
         ));
         $packageManager->_call('scanAvailablePackages');
         $packageManager->_call('sortAndSavePackageStates');
 
         $packageStates = require('vfs://Test/Configuration/PackageStates.php');
-        $this->assertEquals('inactive', $packageStates['packages'][$packageKey]['state']);
+        $this->assertEquals('Application/' . $packageKey . '/', $packageStates['packages'][$packageKey]['packagePath']);
     }
 
     /**
@@ -202,7 +203,7 @@ class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
         }
 
         /** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $packageManager */
-        $packageManager = $this->getAccessibleMock(PackageManager::class, array('dummy'));
+        $packageManager = $this->getAccessibleMock(PackageManager::class, array('sortAndSavePackageStates'));
         $packageManager->_set('packagesBasePaths', $packagePaths);
         $packageManager->_set('packagesBasePath', 'vfs://Test/Packages/');
         $packageManager->_set('packageStatesPathAndFilename', 'vfs://Test/Configuration/PackageStates.php');
@@ -212,7 +213,7 @@ class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
         $dependencyResolver
             ->expects($this->any())
             ->method('sortPackageStatesConfigurationByDependency')
-            ->willReturnArgument(0);
+            ->willReturnCallback('array_keys');
 
         $packageManager->injectDependencyResolver($dependencyResolver);
 
@@ -222,9 +223,9 @@ class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
         $expectedPackageStatesConfiguration = array();
         foreach ($packageKeys as $packageKey) {
             $expectedPackageStatesConfiguration[$packageKey] = array(
-                'state' => 'inactive',
                 'packagePath' => 'Application/' . $packageKey . '/'
             );
+            $packageManager->activatePackage($packageKey);
         }
 
         $actualPackageStatesConfiguration = $packageManager->_get('packageStatesConfiguration');
@@ -268,6 +269,8 @@ class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
 
         $this->createPackage($packageKey);
 
+        $this->packageManager->expects($this->any())->method('sortActivePackagesByDependencies')->will($this->returnValue(array()));
+
         $this->packageManager->deactivatePackage($packageKey);
         $this->assertFalse($this->packageManager->isPackageActive($packageKey));
 
@@ -283,6 +286,7 @@ class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
     {
         $package = $this->createPackage('Acme.YetAnotherTestPackage');
         $package->setProtected(true);
+        $this->packageManager->expects($this->any())->method('sortActivePackagesByDependencies')->will($this->returnValue(array()));
         $this->packageManager->deactivatePackage('Acme.YetAnotherTestPackage');
     }
 
@@ -292,6 +296,7 @@ class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function deletePackageThrowsErrorIfPackageIsNotAvailable()
     {
+        $this->packageManager->expects($this->any())->method('sortActivePackagesByDependencies')->will($this->returnValue(array()));
         $this->packageManager->deletePackage('PrettyUnlikelyThatThisPackageExists');
     }
 
@@ -313,6 +318,8 @@ class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
     {
         $this->createPackage('Acme.YetAnotherTestPackage');
 
+        $this->packageManager->expects($this->any())->method('sortActivePackagesByDependencies')->will($this->returnValue(array()));
+
         $this->assertTrue($this->packageManager->isPackageActive('Acme.YetAnotherTestPackage'));
         $this->assertTrue($this->packageManager->isPackageAvailable('Acme.YetAnotherTestPackage'));