+++ /dev/null
-<?php
-namespace TYPO3\CMS\Core\Package;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Service\DependencyOrderingService;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-
-/**
- * This class takes care about dependencies between packages.
- * It provides functionality to resolve dependencies and to determine
- * the crucial loading order of the packages.
- * @deprecated since TYPO3 v9.2, will be removed in TYPO3 v10.0
- */
-class DependencyResolver
-{
- /**
- * @var DependencyOrderingService
- */
- protected $dependencyOrderingService;
-
- /**
- * @param DependencyOrderingService $dependencyOrderingService
- */
- public function injectDependencyOrderingService(DependencyOrderingService $dependencyOrderingService)
- {
- $this->dependencyOrderingService = $dependencyOrderingService;
- }
-
- /**
- * @param array $packageStatesConfiguration
- * @return array Returns the packageStatesConfiguration sorted by dependencies
- * @throws \UnexpectedValueException
- */
- public function sortPackageStatesConfigurationByDependency(array $packageStatesConfiguration)
- {
- trigger_error(self::class . ' will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
- return $this->dependencyOrderingService->calculateOrder($this->buildDependencyGraph($packageStatesConfiguration));
- }
-
- /**
- * Convert the package configuration into a dependency definition
- *
- * This converts "dependencies" and "suggestions" to "after" syntax for the usage in DependencyOrderingService
- *
- * @param array $packageStatesConfiguration
- * @param array $packageKeys
- * @return array
- * @throws \UnexpectedValueException
- */
- protected function convertConfigurationForGraph(array $packageStatesConfiguration, array $packageKeys)
- {
- $dependencies = [];
- foreach ($packageKeys as $packageKey) {
- if (!isset($packageStatesConfiguration[$packageKey]['dependencies']) && !isset($packageStatesConfiguration[$packageKey]['suggestions'])) {
- continue;
- }
- $dependencies[$packageKey] = [
- 'after' => []
- ];
- if (isset($packageStatesConfiguration[$packageKey]['dependencies'])) {
- foreach ($packageStatesConfiguration[$packageKey]['dependencies'] as $dependentPackageKey) {
- if (!in_array($dependentPackageKey, $packageKeys, true)) {
- throw new \UnexpectedValueException(
- 'The package "' . $packageKey . '" depends on "'
- . $dependentPackageKey . '" which is not present in the system.',
- 1382276561
- );
- }
- $dependencies[$packageKey]['after'][] = $dependentPackageKey;
- }
- }
- if (isset($packageStatesConfiguration[$packageKey]['suggestions'])) {
- foreach ($packageStatesConfiguration[$packageKey]['suggestions'] as $suggestedPackageKey) {
- // skip suggestions on not existing packages
- if (in_array($suggestedPackageKey, $packageKeys, true)) {
- // Suggestions actually have never been meant to influence loading order.
- // We misuse this currently, as there is no other way to influence the loading order
- // for not-required packages (soft-dependency).
- // When considering suggestions for the loading order, we might create a cyclic dependency
- // if the suggested package already has a real dependency on this package, so the suggestion
- // has do be dropped in this case and must *not* be taken into account for loading order evaluation.
- $dependencies[$packageKey]['after-resilient'][] = $suggestedPackageKey;
- }
- }
- }
- }
- return $dependencies;
- }
-
- /**
- * Adds all root packages of current dependency graph as dependency to all extensions
- *
- * 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
- */
- protected function addDependencyToFrameworkToAllExtensions(array $packageStateConfiguration, array $rootPackageKeys)
- {
- $frameworkPackageKeys = $this->findFrameworkPackages($packageStateConfiguration);
- $extensionPackageKeys = array_diff(array_keys($packageStateConfiguration), $frameworkPackageKeys);
- foreach ($extensionPackageKeys as $packageKey) {
- // Remove framework packages from list
- $packageKeysWithoutFramework = array_diff(
- $packageStateConfiguration[$packageKey]['dependencies'],
- $frameworkPackageKeys
- );
- // The order of the array_merge is crucial here,
- // we want the framework first
- $packageStateConfiguration[$packageKey]['dependencies'] = array_merge(
- $rootPackageKeys,
- $packageKeysWithoutFramework
- );
- }
- return $packageStateConfiguration;
- }
-
- /**
- * Builds the dependency graph for all packages
- *
- * 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
- */
- protected function buildDependencyGraph(array $packageStateConfiguration)
- {
- $frameworkPackageKeys = $this->findFrameworkPackages($packageStateConfiguration);
- $frameworkPackagesDependencyGraph = $this->dependencyOrderingService->buildDependencyGraph($this->convertConfigurationForGraph($packageStateConfiguration, $frameworkPackageKeys));
- $packageStateConfiguration = $this->addDependencyToFrameworkToAllExtensions($packageStateConfiguration, $this->dependencyOrderingService->findRootIds($frameworkPackagesDependencyGraph));
-
- $packageKeys = array_keys($packageStateConfiguration);
- return $this->dependencyOrderingService->buildDependencyGraph($this->convertConfigurationForGraph($packageStateConfiguration, $packageKeys));
- }
-
- /**
- * @param array $packageStateConfiguration
- * @return array
- */
- protected function findFrameworkPackages(array $packageStateConfiguration)
- {
- $frameworkPackageKeys = [];
- $packageManager = GeneralUtility::makeInstance(PackageManager::class);
- foreach ($packageStateConfiguration as $packageKey => $packageConfiguration) {
- /** @var Package $package */
- $package = $packageManager->getPackage($packageKey);
- if ($package->getValueFromComposerManifest('type') === 'typo3-cms-framework') {
- $frameworkPackageKeys[] = $packageKey;
- }
- }
-
- return $frameworkPackageKeys;
- }
-}
/**
* @param DependencyOrderingService $dependencyOrderingService
*/
- public function __construct(DependencyOrderingService $dependencyOrderingService = null)
+ public function __construct(DependencyOrderingService $dependencyOrderingService)
{
$this->packagesBasePath = Environment::getPublicPath() . '/';
$this->packageStatesPathAndFilename = Environment::getLegacyConfigPath() . '/PackageStates.php';
- if ($dependencyOrderingService === null) {
- trigger_error(self::class . ' without constructor based dependency injection will stop working in TYPO3 v10.0.', E_USER_DEPRECATED);
- $dependencyOrderingService = GeneralUtility::makeInstance(DependencyOrderingService::class);
- }
$this->dependencyOrderingService = $dependencyOrderingService;
}
$this->coreCache = $coreCache;
}
- /**
- * @param DependencyResolver $dependencyResolver
- * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
- * @internal
- */
- public function injectDependencyResolver(DependencyResolver $dependencyResolver)
- {
- trigger_error(self::class . '::injectDependencyResolver() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
- }
-
/**
* Initializes the package manager
* @internal
}
}
- // @internal DependencyResolver
+ // @internal PackageManager
// this is a dirty special case for suggestion handling of packages
- // see \TYPO3\CMS\Core\Package\DependencyResolver::convertConfigurationForGraph for details
+ // see \TYPO3\CMS\Core\Package\PackageManager::convertConfigurationForGraph for details
// DO NOT use this for any other case
foreach ($identifiers as $id) {
if (isset($dependencies[$id]['after-resilient'])) {
* :php:`TYPO3\CMS\Core\Crypto\PasswordHashing\SaltedPasswordService`
* :php:`TYPO3\CMS\Core\Crypto\PasswordHashing\SaltedPasswordsUtility`
* :php:`TYPO3\CMS\Core\Encoder\JavaScriptEncoder`
+* :php:`TYPO3\CMS\Core\Package\DependencyResolver`
* :php:`TYPO3\CMS\Core\Resource\Utility\BackendUtility`
* :php:`TYPO3\CMS\Core\Utility\ClientUtility`
* :php:`TYPO3\CMS\Core\Utility\PhpOptionsUtility`
* :php:`TYPO3\CMS\Core\Crypto\PasswordHashing\PhpassPasswordHash->setHashCount()`
* :php:`TYPO3\CMS\Core\Crypto\PasswordHashing\PhpassPasswordHash->setMaxHashCount()`
* :php:`TYPO3\CMS\Core\Crypto\PasswordHashing\PhpassPasswordHash->setMinHashCount()`
+* :php:`TYPO3\CMS\Core\Package\PackageManager->injectDependencyResolver()`
* :php:`TYPO3\CMS\Core\TypoScript\TemplateService->getFileName()`
* :php:`TYPO3\CMS\Core\TypoScript\TemplateService->getFromMPmap()`
* :php:`TYPO3\CMS\Core\TypoScript\TemplateService->init()`
* :php:`TYPO3\CMS\Core\Crypto\PasswordHashing\Pbkdf2PasswordHash->getHashedPassword()` - Second argument dropped
* :php:`TYPO3\CMS\Core\Crypto\PasswordHashing\PhpassPasswordHash->getHashedPassword()` - Second argument dropped
* :php:`TYPO3\CMS\Core\Http\Dispatcher->dispatch()` - Second argument dropped
+* :php:`TYPO3\CMS\Core\Package\PackageManager->__construct()` - First argument mandatory
* :php:`TYPO3\CMS\Frontend\Page\PageRepository->getRawRecord()` - Fourth argument dropped
+++ /dev/null
-<?php
-namespace TYPO3\CMS\Core\Tests\Unit\Package;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Package\DependencyResolver;
-use TYPO3\CMS\Core\Service\DependencyOrderingService;
-use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
-
-/**
- * Test case
- */
-class DependencyResolverTest extends UnitTestCase
-{
- /**
- * @test
- * @param array $unsortedPackageStatesConfiguration
- * @param array $frameworkPackageKeys
- * @param array $expectedGraph
- * @dataProvider buildDependencyGraphBuildsCorrectGraphDataProvider
- */
- public function buildDependencyGraphBuildsCorrectGraph(array $unsortedPackageStatesConfiguration, array $frameworkPackageKeys, array $expectedGraph)
- {
- /** @var DependencyResolver|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface $dependencyResolver */
- $dependencyResolver = $this->getAccessibleMock(DependencyResolver::class, ['findFrameworkPackages']);
- $dependencyResolver->injectDependencyOrderingService(new DependencyOrderingService());
- $dependencyResolver->expects($this->any())->method('findFrameworkPackages')->willReturn($frameworkPackageKeys);
- $dependencyGraph = $dependencyResolver->_call('buildDependencyGraph', $unsortedPackageStatesConfiguration);
-
- $this->assertEquals($expectedGraph, $dependencyGraph);
- }
-
- /**
- * @test
- * @dataProvider packageSortingDataProvider
- * @param array $unsortedPackageStatesConfiguration
- * @param array $frameworkPackageKeys
- * @param array $expectedSortedPackageStatesConfiguration
- */
- public function sortPackageStatesConfigurationByDependencyMakesSureThatDependantPackagesAreStandingBeforeAPackageInTheInternalPackagesAndPackagesConfigurationArrays($unsortedPackageStatesConfiguration, $frameworkPackageKeys, $expectedSortedPackageKeys)
- {
- /** @var DependencyResolver|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface $dependencyResolver */
- $dependencyResolver = $this->getAccessibleMock(DependencyResolver::class, ['findFrameworkPackages']);
- $dependencyResolver->injectDependencyOrderingService(new DependencyOrderingService());
- $dependencyResolver->expects($this->any())->method('findFrameworkPackages')->willReturn($frameworkPackageKeys);
- $sortedPackageKeys = $dependencyResolver->_call('sortPackageStatesConfigurationByDependency', $unsortedPackageStatesConfiguration);
-
- $this->assertEquals($expectedSortedPackageKeys, $sortedPackageKeys, 'The package states configurations have not been ordered according to their dependencies!');
- }
-
- /**
- * @test
- */
- public function sortPackageStatesConfigurationByDependencyThrowsExceptionWhenCycleDetected()
- {
- $unsortedPackageStatesConfiguration = [
- 'A' => [
- 'dependencies' => ['B'],
- ],
- 'B' => [
- 'dependencies' => ['A']
- ],
- ];
-
- $this->expectException(\UnexpectedValueException::class);
- $this->expectExceptionCode(1381960494);
-
- /** @var DependencyResolver|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface $dependencyResolver */
- $dependencyResolver = $this->getAccessibleMock(DependencyResolver::class, ['findFrameworkPackages']);
- $dependencyResolver->injectDependencyOrderingService(new DependencyOrderingService());
- $dependencyResolver->expects($this->any())->method('findFrameworkPackages')->willReturn([]);
- $dependencyResolver->_call('sortPackageStatesConfigurationByDependency', $unsortedPackageStatesConfiguration);
- }
-
- /**
- * @return array
- */
- public function buildDependencyGraphBuildsCorrectGraphDataProvider()
- {
- return [
- 'TYPO3 Flow Packages' => [
- [
- 'TYPO3.Flow' => [
- 'dependencies' => ['Symfony.Component.Yaml', 'Doctrine.Common', 'Doctrine.DBAL', 'Doctrine.ORM']
- ],
- 'Doctrine.ORM' => [
- 'dependencies' => ['Doctrine.Common', 'Doctrine.DBAL']
- ],
- 'Doctrine.Common' => [
- 'dependencies' => []
- ],
- 'Doctrine.DBAL' => [
- 'dependencies' => ['Doctrine.Common']
- ],
- 'Symfony.Component.Yaml' => [
- 'dependencies' => []
- ],
- ],
- [
- 'Doctrine.Common'
- ],
- [
- 'TYPO3.Flow' => [
- 'TYPO3.Flow' => false,
- 'Doctrine.ORM' => true,
- 'Doctrine.Common' => true,
- 'Doctrine.DBAL' => true,
- 'Symfony.Component.Yaml' => true,
- ],
- 'Doctrine.ORM' => [
- 'TYPO3.Flow' => false,
- 'Doctrine.ORM' => false,
- 'Doctrine.Common' => true,
- 'Doctrine.DBAL' => true,
- 'Symfony.Component.Yaml' => false,
- ],
- 'Doctrine.Common' => [
- 'TYPO3.Flow' => false,
- 'Doctrine.ORM' => false,
- 'Doctrine.Common' => false,
- 'Doctrine.DBAL' => false,
- 'Symfony.Component.Yaml' => false,
- ],
- 'Doctrine.DBAL' => [
- 'TYPO3.Flow' => false,
- 'Doctrine.ORM' => false,
- 'Doctrine.Common' => true,
- 'Doctrine.DBAL' => false,
- 'Symfony.Component.Yaml' => false,
- ],
- 'Symfony.Component.Yaml' => [
- 'TYPO3.Flow' => false,
- 'Doctrine.ORM' => false,
- 'Doctrine.Common' => true,
- 'Doctrine.DBAL' => false,
- 'Symfony.Component.Yaml' => false,
- ],
- ],
- ],
- 'TYPO3 CMS Extensions' => [
- [
- 'core' => [
- 'dependencies' => [],
- ],
- 'setup' => [
- 'dependencies' => ['core'],
- ],
- 'openid' => [
- 'dependencies' => ['core', 'setup']
- ],
- 'news' => [
- 'dependencies' => ['extbase'],
- ],
- 'extbase' => [
- 'dependencies' => ['core'],
- ],
- 'pt_extbase' => [
- 'dependencies' => ['extbase'],
- ],
- 'foo' => [
- 'dependencies' => [],
- ],
- ],
- [
- 'core',
- 'setup',
- 'openid',
- 'extbase'
- ],
- [
- 'core' => [
- 'core' => false,
- 'setup' => false,
- 'openid' => false,
- 'news' => false,
- 'extbase' => false,
- 'pt_extbase' => false,
- 'foo' => false
- ],
- 'setup' => [
- 'core' => true,
- 'setup' => false,
- 'openid' => false,
- 'news' => false,
- 'extbase' => false,
- 'pt_extbase' => false,
- 'foo' => false
- ],
- 'openid' => [
- 'core' => true,
- 'setup' => true,
- 'openid' => false,
- 'news' => false,
- 'extbase' => false,
- 'pt_extbase' => false,
- 'foo' => false
- ],
- 'news' => [
- 'core' => false,
- 'setup' => false,
- 'openid' => true,
- 'news' => false,
- 'extbase' => true,
- 'pt_extbase' => false,
- 'foo' => false
- ],
- 'extbase' => [
- 'core' => true,
- 'setup' => false,
- 'openid' => false,
- 'news' => false,
- 'extbase' => false,
- 'pt_extbase' => false,
- 'foo' => false
- ],
- 'pt_extbase' => [
- 'core' => false,
- 'setup' => false,
- 'openid' => true,
- 'news' => false,
- 'extbase' => true,
- 'pt_extbase' => false,
- 'foo' => false
- ],
- 'foo' => [
- 'core' => false,
- 'setup' => false,
- 'openid' => true,
- 'news' => false,
- 'extbase' => true,
- 'pt_extbase' => false,
- 'foo' => false
- ],
- ],
- ],
- 'Dummy Packages' => [
- [
- 'A' => [
- 'dependencies' => ['B', 'D', 'C'],
- ],
- 'B' => [
- 'dependencies' => []
- ],
- 'C' => [
- 'dependencies' => ['E']
- ],
- 'D' => [
- 'dependencies' => ['E'],
- ],
- 'E' => [
- 'dependencies' => [],
- ],
- 'F' => [
- 'dependencies' => [],
- ],
- ],
- [
- 'B',
- 'C',
- 'E'
- ],
- [
- 'A' => [
- 'A' => false,
- 'B' => true,
- 'C' => true,
- 'D' => true,
- 'E' => false,
- 'F' => false,
- ],
- 'B' => [
- 'A' => false,
- 'B' => false,
- 'C' => false,
- 'D' => false,
- 'E' => false,
- 'F' => false,
- ],
- 'C' => [
- 'A' => false,
- 'B' => false,
- 'C' => false,
- 'D' => false,
- 'E' => true,
- 'F' => false,
- ],
- 'D' => [
- 'A' => false,
- 'B' => true,
- 'C' => true,
- 'D' => false,
- 'E' => false,
- 'F' => false,
- ],
- 'E' => [
- 'A' => false,
- 'B' => false,
- 'C' => false,
- 'D' => false,
- 'E' => false,
- 'F' => false,
- ],
- 'F' => [
- 'A' => false,
- 'B' => true,
- 'C' => true,
- 'D' => false,
- 'E' => false,
- 'F' => false,
- ],
- ],
- ],
- ];
- }
-
- /**
- * @return array
- */
- public function packageSortingDataProvider()
- {
- return [
- 'TYPO3 Flow Packages' => [
- [
- 'TYPO3.Flow' => [
- 'dependencies' => ['Symfony.Component.Yaml', 'Doctrine.Common', 'Doctrine.DBAL', 'Doctrine.ORM']
- ],
- 'Doctrine.ORM' => [
- 'dependencies' => ['Doctrine.Common', 'Doctrine.DBAL']
- ],
- 'Doctrine.Common' => [
- 'dependencies' => []
- ],
- 'Doctrine.DBAL' => [
- 'dependencies' => ['Doctrine.Common']
- ],
- 'Symfony.Component.Yaml' => [
- 'dependencies' => []
- ],
- ],
- [
- 'Doctrine.Common'
- ],
- [
- 'Doctrine.Common',
- 'Doctrine.DBAL',
- 'Doctrine.ORM',
- 'Symfony.Component.Yaml',
- 'TYPO3.Flow',
- ],
- ],
- 'TYPO3 CMS Extensions' => [
- [
- 'core' => [
- 'dependencies' => [],
- ],
- 'setup' => [
- 'dependencies' => ['core'],
- ],
- 'openid' => [
- 'dependencies' => ['core', 'setup']
- ],
- 'news' => [
- 'dependencies' => ['extbase'],
- ],
- 'extbase' => [
- 'dependencies' => ['core'],
- ],
- 'pt_extbase' => [
- 'dependencies' => ['extbase'],
- ],
- 'foo' => [
- 'dependencies' => [],
- ],
- ],
- [
- 'core',
- 'setup',
- 'openid',
- 'extbase'
- ],
- [
- 'core',
- 'setup',
- 'openid',
- 'extbase',
- 'foo',
- 'news',
- 'pt_extbase',
- ],
- ],
- 'Dummy Packages' => [
- [
- 'A' => [
- 'dependencies' => ['B', 'D', 'C'],
- ],
- 'B' => [
- 'dependencies' => []
- ],
- 'C' => [
- 'dependencies' => ['E']
- ],
- 'D' => [
- 'dependencies' => ['E'],
- ],
- 'E' => [
- 'dependencies' => [],
- ],
- 'F' => [
- 'dependencies' => [],
- ],
- ],
- [
- 'B',
- 'C',
- 'E'
- ],
- [
- 'E',
- 'C',
- 'B',
- 'D',
- 'A',
- 'F',
- ],
- ],
- ];
- }
-}
$packageName = $this->getUniqueId('foo');
/** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
$packageManager = $this->getMockBuilder(PackageManager::class)
+ ->disableOriginalConstructor()
->setMethods(['isPackageActive'])
->getMock();
$packageManager->expects($this->once())
->getMock();
/** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
$packageManager = $this->getMockBuilder(PackageManager::class)
+ ->disableOriginalConstructor()
->setMethods(['isPackageActive', 'getPackage'])
->getMock();
$package->expects($this->once())
->will($this->returnValue($extensionKey));
/** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
$packageManager = $this->getMockBuilder(PackageManager::class)
+ ->disableOriginalConstructor()
->setMethods(['getActivePackages'])
->getMock();
$packageManager->expects($this->once())
->will($this->returnValue($extensionKey));
/** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
$packageManager = $this->getMockBuilder(PackageManager::class)
+ ->disableOriginalConstructor()
->setMethods(['getActivePackages'])
->getMock();
$packageManager->expects($this->once())
'TYPO3\CMS\Core\Package\DependencyResolver' => [
'restFiles' => [
'Deprecation-84109-DeprecateDependencyResolver.rst',
+ 'Breaking-87193-DeprecatedFunctionalityRemoved.rst',
],
],
'TYPO3\CMS\Recordlist\RecordList' => [
'maximumNumberOfArguments' => 1,
'restFiles' => [
'Deprecation-84109-DeprecateDependencyResolver.rst',
+ 'Breaking-87193-DeprecatedFunctionalityRemoved.rst',
],
],
'TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->calculateLinkVars' => [
'maximumNumberOfArguments' => 1,
'restFiles' => [
'Deprecation-84109-DeprecateDependencyResolver.rst',
+ 'Breaking-87193-DeprecatedFunctionalityRemoved.rst',
],
],
'TYPO3\CMS\Backend\Controller\EditDocumentController->preInit' => [