[BUGFIX] Select suitable distribution version in em 76/53276/2
authorChristian Kuhn <lolli@schwarzbu.ch>
Sun, 18 Jun 2017 11:48:56 +0000 (13:48 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Tue, 20 Jun 2017 10:24:38 +0000 (12:24 +0200)
The distribution installer selects current_version=1
extensons only and fails in core v7 since the current
introduction version is not compatible with v7 anymore.

The patch changes version selection a bit to first find
all distribution extensions, then filters those suitable
for given core version, then filters latest version of
the distribution extension.

Installing introduction package in 7.6 works again.

Change-Id: I11f2def2ea606ada5f7c3efd3043f59bd4be0452
Resolves: #81068
Releases: master, 8.7, 7.6
Reviewed-on: https://review.typo3.org/53276
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/extensionmanager/Classes/Controller/ListController.php
typo3/sysext/extensionmanager/Classes/Domain/Repository/ExtensionRepository.php
typo3/sysext/extensionmanager/Classes/Utility/DependencyUtility.php
typo3/sysext/extensionmanager/Tests/Unit/Utility/DependencyUtilityTest.php

index 7e4d666..f2c3c7a 100644 (file)
@@ -227,15 +227,11 @@ class ListController extends AbstractModuleController
             $officialDistributions = $this->extensionRepository->findAllOfficialDistributions();
             $communityDistributions = $this->extensionRepository->findAllCommunityDistributions();
 
-            if (!$showUnsuitableDistributions) {
-                $suitableOfficialDistributions = $this->dependencyUtility->getExtensionsSuitableForTypo3Version($officialDistributions);
-                $this->view->assign('officialDistributions', $suitableOfficialDistributions);
-                $suitableCommunityDistributions = $this->dependencyUtility->getExtensionsSuitableForTypo3Version($communityDistributions);
-                $this->view->assign('communityDistributions', $suitableCommunityDistributions);
-            } else {
-                $this->view->assign('officialDistributions', $officialDistributions);
-                $this->view->assign('communityDistributions', $communityDistributions);
-            }
+            $officialDistributions = $this->dependencyUtility->filterYoungestVersionOfExtensionList($officialDistributions->toArray(), $showUnsuitableDistributions);
+            $communityDistributions = $this->dependencyUtility->filterYoungestVersionOfExtensionList($communityDistributions->toArray(), $showUnsuitableDistributions);
+
+            $this->view->assign('officialDistributions', $officialDistributions);
+            $this->view->assign('communityDistributions', $communityDistributions);
         }
         $this->view->assign('enableDistributionsView', $importExportInstalled);
         $this->view->assign('showUnsuitableDistributions', $showUnsuitableDistributions);
index abd7b7f..b4c61eb 100644 (file)
@@ -252,7 +252,6 @@ class ExtensionRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
         $query->matching(
             $query->logicalAnd(
                 $query->equals('category', \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::DISTRIBUTION_CATEGORY),
-                $query->equals('currentVersion', 1),
                 $query->logicalNot($query->equals('ownerusername', 'typo3v4'))
             )
         );
@@ -275,7 +274,6 @@ class ExtensionRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
         $query->matching(
             $query->logicalAnd(
                 $query->equals('category', \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::DISTRIBUTION_CATEGORY),
-                $query->equals('currentVersion', 1),
                 $query->equals('ownerusername', 'typo3v4')
             )
         );
index 77e6bfd..2960723 100644 (file)
@@ -602,4 +602,36 @@ class DependencyUtility implements \TYPO3\CMS\Core\SingletonInterface
         }
         return $suitableExtensions;
     }
+
+    /**
+     * Gets a list of various extensions in various versions and returns
+     * a filtered list containing the extension-version combination with
+     * the highest version number.
+     *
+     * @param Extension[] $extensions
+     * @param bool $showUnsuitable
+     *
+     * @return \TYPO3\CMS\Extensionmanager\Domain\Model\Extension[]
+     */
+    public function filterYoungestVersionOfExtensionList(array $extensions, $showUnsuitable)
+    {
+        if (!$showUnsuitable) {
+            $extensions = $this->getExtensionsSuitableForTypo3Version($extensions);
+        }
+        $filteredExtensions = [];
+        foreach ($extensions as $extension) {
+            $extensionKey = $extension->getExtensionKey();
+            if (!array_key_exists($extensionKey, $filteredExtensions)) {
+                $filteredExtensions[$extensionKey] = $extension;
+                continue;
+            } else {
+                $currentVersion = $filteredExtensions[$extensionKey]->getVersion();
+                $newVersion = $extension->getVersion();
+                if (version_compare($newVersion, $currentVersion, '>')) {
+                    $filteredExtensions[$extensionKey] = $extension;
+                }
+            }
+        }
+        return $filteredExtensions;
+    }
 }
index f03d540..f72ac20 100644 (file)
@@ -14,12 +14,17 @@ namespace TYPO3\CMS\Extensionmanager\Tests\Unit\Utility;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Extensionmanager\Domain\Model\Dependency;
+use TYPO3\CMS\Extensionmanager\Domain\Model\Extension;
+use TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository;
 use TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException;
+use TYPO3\CMS\Extensionmanager\Utility\DependencyUtility;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
 /**
  * Test for DependencyUtility
  */
-class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+class DependencyUtilityTest extends UnitTestCase
 {
     /**
      * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
@@ -27,6 +32,7 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
     protected $objectManagerMock;
 
     /**
+     * Set up
      */
     protected function setUp()
     {
@@ -38,13 +44,13 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkTypo3DependencyThrowsExceptionIfVersionNumberIsTooLow()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->atLeastOnce())->method('getLowestVersion')->will($this->returnValue('15.0.0'));
         $dependencyMock->setIdentifier('typo3');
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->expectException(ExtensionManagerException::class);
         $this->expectExceptionCode(1399144499);
@@ -56,14 +62,14 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkTypo3DependencyThrowsExceptionIfVersionNumberIsTooHigh()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->atLeastOnce())->method('getHighestVersion')->will($this->returnValue('3.0.0'));
         $dependencyMock->expects($this->atLeastOnce())->method('getLowestVersion')->will($this->returnValue('1.0.0'));
         $dependencyMock->setIdentifier('typo3');
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->expectException(ExtensionManagerException::class);
         $this->expectExceptionCode(1399144521);
@@ -75,12 +81,12 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkTypo3DependencyThrowsExceptionIfIdentifierIsNotTypo3()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->setIdentifier('123');
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->expectException(ExtensionManagerException::class);
         $this->expectExceptionCode(1399144551);
@@ -92,14 +98,14 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkTypo3DependencyReturnsTrueIfVersionNumberIsInRange()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->atLeastOnce())->method('getHighestVersion')->will($this->returnValue('15.0.0'));
         $dependencyMock->expects($this->atLeastOnce())->method('getLowestVersion')->will($this->returnValue('1.0.0'));
         $dependencyMock->setIdentifier('typo3');
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->assertTrue($dependencyUtility->_call('checkTypo3Dependency', $dependencyMock));
     }
@@ -109,14 +115,14 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkTypo3DependencyCanHandleEmptyVersionHighestVersion()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->atLeastOnce())->method('getHighestVersion')->will($this->returnValue(''));
         $dependencyMock->expects($this->atLeastOnce())->method('getLowestVersion')->will($this->returnValue('1.0.0'));
         $dependencyMock->setIdentifier('typo3');
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->assertTrue($dependencyUtility->_call('checkTypo3Dependency', $dependencyMock));
     }
@@ -126,14 +132,14 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkTypo3DependencyCanHandleEmptyVersionLowestVersion()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->atLeastOnce())->method('getHighestVersion')->will($this->returnValue('15.0.0'));
         $dependencyMock->expects($this->atLeastOnce())->method('getLowestVersion')->will($this->returnValue(''));
         $dependencyMock->setIdentifier('typo3');
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->assertTrue($dependencyUtility->_call('checkTypo3Dependency', $dependencyMock));
     }
@@ -143,13 +149,13 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkPhpDependencyThrowsExceptionIfVersionNumberIsTooLow()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->atLeastOnce())->method('getLowestVersion')->will($this->returnValue('15.0.0'));
         $dependencyMock->setIdentifier('php');
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->expectException(ExtensionManagerException::class);
         $this->expectExceptionCode(1377977857);
@@ -161,14 +167,14 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkPhpDependencyThrowsExceptionIfVersionNumberIsTooHigh()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->atLeastOnce())->method('getHighestVersion')->will($this->returnValue('3.0.0'));
         $dependencyMock->expects($this->atLeastOnce())->method('getLowestVersion')->will($this->returnValue('1.0.0'));
         $dependencyMock->setIdentifier('php');
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->expectException(ExtensionManagerException::class);
         $this->expectExceptionCode(1377977856);
@@ -180,12 +186,12 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkPhpDependencyThrowsExceptionIfIdentifierIsNotTypo3()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->setIdentifier('123');
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->expectException(ExtensionManagerException::class);
         $this->expectExceptionCode(1377977858);
@@ -197,14 +203,14 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkPhpDependencyReturnsTrueIfVersionNumberIsInRange()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->atLeastOnce())->method('getHighestVersion')->will($this->returnValue('15.0.0'));
         $dependencyMock->expects($this->atLeastOnce())->method('getLowestVersion')->will($this->returnValue('1.0.0'));
         $dependencyMock->setIdentifier('php');
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->assertTrue($dependencyUtility->_call('checkPhpDependency', $dependencyMock));
     }
@@ -214,14 +220,14 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkPhpDependencyCanHandleEmptyVersionHighestVersion()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->atLeastOnce())->method('getHighestVersion')->will($this->returnValue(''));
         $dependencyMock->expects($this->atLeastOnce())->method('getLowestVersion')->will($this->returnValue('1.0.0'));
         $dependencyMock->setIdentifier('php');
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->assertTrue($dependencyUtility->_call('checkPhpDependency', $dependencyMock));
     }
@@ -231,14 +237,14 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkPhpDependencyCanHandleEmptyVersionLowestVersion()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->atLeastOnce())->method('getHighestVersion')->will($this->returnValue('15.0.0'));
         $dependencyMock->expects($this->atLeastOnce())->method('getLowestVersion')->will($this->returnValue(''));
         $dependencyMock->setIdentifier('php');
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->assertTrue($dependencyUtility->_call('checkPhpDependency', $dependencyMock));
     }
@@ -248,20 +254,20 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkDependenciesCallsMethodToCheckPhpDependencies()
     {
-        /** @var \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionMock */
-        $extensionMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class)
+        /** @var Extension $extensionMock */
+        $extensionMock = $this->getMockBuilder(Extension::class)
             ->setMethods(['dummy'])
             ->getMock();
-        /** @var \TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->setIdentifier('php');
         $dependencyStorage = new \SplObjectStorage();
         $dependencyStorage->attach($dependencyMock);
         $extensionMock->setDependencies($dependencyStorage);
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility $dependencyUtility */
-        $dependencyUtility = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|DependencyUtility $dependencyUtility */
+        $dependencyUtility = $this->getMockBuilder(DependencyUtility::class)
             ->setMethods(['checkPhpDependency', 'checkTypo3Dependency'])
             ->getMock();
         $dependencyUtility->expects($this->atLeastOnce())->method('checkPhpDependency');
@@ -273,20 +279,20 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function checkDependenciesCallsMethodToCheckTypo3Dependencies()
     {
-        /** @var \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionMock */
-        $extensionMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class)
+        /** @var Extension $extensionMock */
+        $extensionMock = $this->getMockBuilder(Extension::class)
             ->setMethods(['dummy'])
             ->getMock();
-        /** @var \TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->setIdentifier('typo3');
         $dependencyStorage = new \SplObjectStorage();
         $dependencyStorage->attach($dependencyMock);
         $extensionMock->setDependencies($dependencyStorage);
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility $dependencyUtility */
-        $dependencyUtility = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|DependencyUtility $dependencyUtility */
+        $dependencyUtility = $this->getMockBuilder(DependencyUtility::class)
             ->setMethods(['checkPhpDependency', 'checkTypo3Dependency'])
             ->getMock();
 
@@ -299,14 +305,14 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function isVersionCompatibleReturnsTrueForCompatibleVersion()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->atLeastOnce())->method('getHighestVersion')->will($this->returnValue('15.0.0'));
         $dependencyMock->expects($this->atLeastOnce())->method('getLowestVersion')->will($this->returnValue('1.0.0'));
         $version = '3.3.3';
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->assertTrue($dependencyUtility->_call('isVersionCompatible', $version, $dependencyMock));
     }
@@ -316,14 +322,14 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function isVersionCompatibleReturnsFalseForIncompatibleVersion()
     {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency $dependencyMock */
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        /** @var \PHPUnit_Framework_MockObject_MockObject|Dependency $dependencyMock */
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->atLeastOnce())->method('getHighestVersion')->will($this->returnValue('1.0.1'));
         $dependencyMock->expects($this->atLeastOnce())->method('getLowestVersion')->will($this->returnValue('1.0.0'));
         $version = '3.3.3';
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
 
         $this->assertFalse($dependencyUtility->_call('isVersionCompatible', $version, $dependencyMock));
     }
@@ -342,7 +348,7 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
             ->setMethods(['getAvailableExtensions'])
             ->getMock();
         $listUtilityMock->expects($this->atLeastOnce())->method('getAvailableExtensions')->will($this->returnValue($availableExtensions));
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
         $dependencyUtility->_set('listUtility', $listUtilityMock);
 
         $this->assertTrue($dependencyUtility->_call('isDependentExtensionAvailable', 'dummy'));
@@ -362,7 +368,7 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
             ->setMethods(['getAvailableExtensions'])
             ->getMock();
         $listUtilityMock->expects($this->atLeastOnce())->method('getAvailableExtensions')->will($this->returnValue($availableExtensions));
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
         $dependencyUtility->_set('listUtility', $listUtilityMock);
 
         $this->assertFalse($dependencyUtility->_call('isDependentExtensionAvailable', '42'));
@@ -380,8 +386,8 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
             'key' => 'dummy',
             'version' => '1.0.0'
         ]));
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['setAvailableExtensions', 'isVersionCompatible']);
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['setAvailableExtensions', 'isVersionCompatible']);
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getIdentifier'])
             ->getMock();
         $dependencyMock->expects($this->once())->method('getIdentifier')->will($this->returnValue('dummy'));
@@ -401,12 +407,12 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function isExtensionDownloadableFromTerReturnsTrueIfOneVersionExists()
     {
-        $extensionRepositoryMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository::class)
+        $extensionRepositoryMock = $this->getMockBuilder(ExtensionRepository::class)
             ->setMethods(['countByExtensionKey'])
             ->setConstructorArgs([$this->objectManagerMock])
             ->getMock();
         $extensionRepositoryMock->expects($this->once())->method('countByExtensionKey')->with('test123')->will($this->returnValue(1));
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
         $dependencyUtility->_set('extensionRepository', $extensionRepositoryMock);
         $count = $dependencyUtility->_call('isExtensionDownloadableFromTer', 'test123');
 
@@ -418,12 +424,12 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function isExtensionDownloadableFromTerReturnsFalseIfNoVersionExists()
     {
-        $extensionRepositoryMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository::class)
+        $extensionRepositoryMock = $this->getMockBuilder(ExtensionRepository::class)
             ->setMethods(['countByExtensionKey'])
             ->setConstructorArgs([$this->objectManagerMock])
             ->getMock();
         $extensionRepositoryMock->expects($this->once())->method('countByExtensionKey')->with('test123')->will($this->returnValue(0));
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
         $dependencyUtility->_set('extensionRepository', $extensionRepositoryMock);
         $count = $dependencyUtility->_call('isExtensionDownloadableFromTer', 'test123');
 
@@ -435,18 +441,18 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function isDownloadableVersionCompatibleReturnsTrueIfCompatibleVersionExists()
     {
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getIdentifier', 'getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->once())->method('getIdentifier')->will($this->returnValue('dummy'));
         $dependencyMock->expects($this->once())->method('getHighestVersion')->will($this->returnValue('10.0.0'));
         $dependencyMock->expects($this->once())->method('getLowestVersion')->will($this->returnValue('1.0.0'));
-        $extensionRepositoryMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository::class)
+        $extensionRepositoryMock = $this->getMockBuilder(ExtensionRepository::class)
             ->setMethods(['countByVersionRangeAndExtensionKey'])
             ->setConstructorArgs([$this->objectManagerMock])
             ->getMock();
         $extensionRepositoryMock->expects($this->once())->method('countByVersionRangeAndExtensionKey')->with('dummy', 1000000, 10000000)->will($this->returnValue(2));
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
         $dependencyUtility->_set('extensionRepository', $extensionRepositoryMock);
         $count = $dependencyUtility->_call('isDownloadableVersionCompatible', $dependencyMock);
 
@@ -458,16 +464,16 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function isDownloadableVersionCompatibleReturnsFalseIfIncompatibleVersionExists()
     {
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getIdentifier'])
             ->getMock();
         $dependencyMock->expects($this->once())->method('getIdentifier')->will($this->returnValue('dummy'));
-        $extensionRepositoryMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository::class)
+        $extensionRepositoryMock = $this->getMockBuilder(ExtensionRepository::class)
             ->setMethods(['countByVersionRangeAndExtensionKey'])
             ->setConstructorArgs([$this->objectManagerMock])
             ->getMock();
         $extensionRepositoryMock->expects($this->once())->method('countByVersionRangeAndExtensionKey')->with('dummy', 1000000, 2000000)->will($this->returnValue(0));
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['getLowestAndHighestIntegerVersions']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['getLowestAndHighestIntegerVersions']);
         $dependencyUtility->_set('extensionRepository', $extensionRepositoryMock);
         $dependencyUtility->expects($this->once())->method('getLowestAndHighestIntegerVersions')->will($this->returnValue([
             'lowestIntegerVersion' => 1000000,
@@ -488,12 +494,12 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
             'highestIntegerVersion' => 2000000
         ];
 
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getHighestVersion', 'getLowestVersion'])
             ->getMock();
         $dependencyMock->expects($this->once())->method('getHighestVersion')->will($this->returnValue('2.0.0'));
         $dependencyMock->expects($this->once())->method('getLowestVersion')->will($this->returnValue('1.0.0'));
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['dummy']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['dummy']);
         $versions = $dependencyUtility->_call('getLowestAndHighestIntegerVersions', $dependencyMock);
 
         $this->assertSame($expectedVersions, $versions);
@@ -504,26 +510,26 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
      */
     public function getLatestCompatibleExtensionByIntegerVersionDependencyWillReturnExtensionModelOfLatestExtension()
     {
-        $extension1 = new \TYPO3\CMS\Extensionmanager\Domain\Model\Extension();
+        $extension1 = new Extension();
         $extension1->setExtensionKey('foo');
         $extension1->setVersion('1.0.0');
-        $extension2 = new \TYPO3\CMS\Extensionmanager\Domain\Model\Extension();
+        $extension2 = new Extension();
         $extension2->setExtensionKey('bar');
         $extension2->setVersion('1.0.42');
 
         $myStorage = new \TYPO3\CMS\Extensionmanager\Tests\Unit\Fixtures\LatestCompatibleExtensionObjectStorageFixture();
         $myStorage->extensions[] = $extension1;
         $myStorage->extensions[] = $extension2;
-        $dependencyMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency::class)
+        $dependencyMock = $this->getMockBuilder(Dependency::class)
             ->setMethods(['getIdentifier'])
             ->getMock();
         $dependencyMock->expects($this->once())->method('getIdentifier')->will($this->returnValue('foobar'));
-        $dependencyUtility = $this->getAccessibleMock(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility::class, ['getLowestAndHighestIntegerVersions']);
+        $dependencyUtility = $this->getAccessibleMock(DependencyUtility::class, ['getLowestAndHighestIntegerVersions']);
         $dependencyUtility->expects($this->once())->method('getLowestAndHighestIntegerVersions')->will($this->returnValue([
             'lowestIntegerVersion' => 1000000,
             'highestIntegerVersion' => 2000000
         ]));
-        $extensionRepositoryMock = $this->getMockBuilder(\TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository::class)
+        $extensionRepositoryMock = $this->getMockBuilder(ExtensionRepository::class)
             ->setMethods(['findByVersionRangeAndExtensionKeyOrderedByVersion'])
             ->setConstructorArgs([$this->objectManagerMock])
             ->getMock();
@@ -531,7 +537,80 @@ class DependencyUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa
         $dependencyUtility->_set('extensionRepository', $extensionRepositoryMock);
         $extension = $dependencyUtility->_call('getLatestCompatibleExtensionByIntegerVersionDependency', $dependencyMock);
 
-        $this->assertInstanceOf(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, $extension);
+        $this->assertInstanceOf(Extension::class, $extension);
         $this->assertSame('foo', $extension->getExtensionKey());
     }
+
+    /**
+     * @test
+     */
+    public function filterYoungestVersionOfExtensionListFiltersAListToLatestVersion()
+    {
+        // foo2 should be kept
+        $foo1 = new Extension();
+        $foo1->setExtensionKey('foo');
+        $foo1->setVersion('1.0.0');
+        $foo2 = new Extension();
+        $foo2->setExtensionKey('foo');
+        $foo2->setVersion('1.0.1');
+
+        // bar1 should be kept
+        $bar1 = new Extension();
+        $bar1->setExtensionKey('bar');
+        $bar1->setVersion('1.1.2');
+        $bar2 = new Extension();
+        $bar2->setExtensionKey('bar');
+        $bar2->setVersion('1.1.1');
+        $bar3 = new Extension();
+        $bar3->setExtensionKey('bar');
+        $bar3->setVersion('1.0.3');
+
+        $input = [$foo1, $foo2, $bar1, $bar2, $bar3];
+        $this->assertEquals(['foo' => $foo2, 'bar' => $bar1], (new DependencyUtility())->filterYoungestVersionOfExtensionList($input, true));
+    }
+
+    /**
+     * @test
+     */
+    public function filterYoungestVersionOfExtensionListFiltersAListToLatestVersionWithOnlyCompatibleExtensions()
+    {
+        $suitableDependency = new Dependency();
+        $suitableDependency->setIdentifier('typo3');
+        $suitableDependency->setLowestVersion('3.6.1');
+
+        $suitableDependencies = new \SplObjectStorage();
+        $suitableDependencies->attach($suitableDependency);
+
+        $unsuitableDependency = new Dependency();
+        $unsuitableDependency->setIdentifier('typo3');
+        $unsuitableDependency->setHighestVersion('4.3.0');
+
+        $unsuitableDependencies = new \SplObjectStorage();
+        $unsuitableDependencies->attach($unsuitableDependency);
+
+        // foo1 should be kept
+        $foo1 = new Extension();
+        $foo1->setExtensionKey('foo');
+        $foo1->setVersion('1.0.0');
+        $foo1->setDependencies($suitableDependencies);
+
+        $foo2 = new Extension();
+        $foo2->setExtensionKey('foo');
+        $foo2->setVersion('1.0.1');
+        $foo2->setDependencies($unsuitableDependencies);
+
+        // bar2 should be kept
+        $bar1 = new Extension();
+        $bar1->setExtensionKey('bar');
+        $bar1->setVersion('1.1.2');
+        $bar1->setDependencies($unsuitableDependencies);
+
+        $bar2 = new Extension();
+        $bar2->setExtensionKey('bar');
+        $bar2->setVersion('1.1.1');
+        $bar2->setDependencies($suitableDependencies);
+
+        $input = [$foo1, $foo2, $bar1, $bar2];
+        $this->assertEquals(['foo' => $foo1, 'bar' => $bar2], (new DependencyUtility())->filterYoungestVersionOfExtensionList($input, false));
+    }
 }