Commit c020e9ba authored by Benjamin Franzke's avatar Benjamin Franzke Committed by Susanne Moog
Browse files

[TASK] Inject singletons used by EXT:install in service providers

This will allow both, dependency injection for these services (manually
wired in service providers), and usage in install/maintenance tool
(where we do not use the caching symfony container for basic tasks).

The move to DI is possible thanks to the failsafe container and the
service providers which can fed the failsafe container with service
factories. These factories are used to wire services manually.

Notes:

 * The definition in a service provider means we are required to use
   manual wiring and are forced to define the dependencies in the service
   provider when we add new depenencies to services that are being used
   by the install..
   With that approach we can assure that we do not accidentally add new
   dependencies to services which would become available in symfony DI due
   to autowiring, but would be unavailable in the install tool.

 * The install tool has operations that require a booted symfony
   container which is provided by the LateBootService. Services that
   are used in that mode do not need to be listed in service providers.
   Therefore we do only add core services to service providers if they
   are used in a context without a fully booted symfony DI container.

 * GLOBALS['LANG'] mocks in Core\Tests\Unit\DataHandling\DataHandlerTest
   have been removed as the code under test does no longer use
   $GLOBALS['LANG']->csConvObj->substr() but mb_substr. The test had been
   introduced with #68602 but the tested code was adapted in #78670.

 * We got a bit ugly constructs now, where a unit(!) test previously used

     $GLOBALS['LANG'] = new LanguageService();

   …we now have to encode the dependency structure:

     $GLOBALS['LANG'] = new LanguageService(new Locales,
         new LocalizationFactory(
             new LanguageStore,
             $cacheManagerProphecy->reveal()
         )
     );

   This isn't nice, but this change reveals that the affected unit tests
   should either be adapted, removed or be moved to a functional test.
   Such adaption are out of scope for this change.

 * loadExtLocalconfDatabaseAndExtTables() is removed from the
   EXT:install AbstractController, as it hides the implicit dependency
   to LateBootService

 * Nullable constructor arguments have been changed to be non-nullable
   whenever possible. That results in some more test adaptions, but
   reveals, where unit tests rely on implicit dependencies and offers
   better readability and less possible codepaths.

Releases: master
Resolves: #89892
Resolves: #89891
Change-Id: Ib72d6440f81b2c0d05279e8768697c3b48aecfe4
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/62575


Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Susanne Moog's avatarSusanne Moog <look@susi.dev>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Susanne Moog's avatarSusanne Moog <look@susi.dev>
parent e28c4916
......@@ -68,10 +68,10 @@ class IconFactory
* @param EventDispatcherInterface $eventDispatcher
* @param IconRegistry $iconRegistry
*/
public function __construct(EventDispatcherInterface $eventDispatcher = null, IconRegistry $iconRegistry = null)
public function __construct(EventDispatcherInterface $eventDispatcher, IconRegistry $iconRegistry)
{
$this->eventDispatcher = $eventDispatcher ?? GeneralUtility::getContainer()->get(EventDispatcherInterface::class);
$this->iconRegistry = $iconRegistry ?? GeneralUtility::makeInstance(IconRegistry::class);
$this->eventDispatcher = $eventDispatcher;
$this->iconRegistry = $iconRegistry;
$this->recordStatusMapping = $GLOBALS['TYPO3_CONF_VARS']['SYS']['IconFactory']['recordStatusMapping'];
$this->overlayPriorities = $GLOBALS['TYPO3_CONF_VARS']['SYS']['IconFactory']['overlayPriorities'];
}
......
......@@ -105,10 +105,22 @@ class LanguageService
protected $labels = [];
/**
* LanguageService constructor.
* @var Locales
*/
public function __construct()
protected $locales;
/**
* @var LocalizationFactory
*/
protected $localizationFactory;
/**
* @internal use one of the factory methods instead
*/
public function __construct(Locales $locales, LocalizationFactory $localizationFactory)
{
$this->locales = $locales;
$this->localizationFactory = $localizationFactory;
$this->debugKey = (bool)$GLOBALS['TYPO3_CONF_VARS']['BE']['languageDebug'];
}
......@@ -124,13 +136,12 @@ class LanguageService
public function init($languageKey)
{
// Find the requested language in this list based on the $languageKey
$locales = GeneralUtility::makeInstance(Locales::class);
// Language is found. Configure it:
if (in_array($languageKey, $locales->getLocales(), true)) {
if (in_array($languageKey, $this->locales->getLocales(), true)) {
// The current language key
$this->lang = $languageKey;
$this->languageDependencies[] = $languageKey;
foreach ($locales->getLocaleDependencies($languageKey) as $language) {
foreach ($this->locales->getLocaleDependencies($languageKey) as $language) {
$this->languageDependencies[] = $language;
}
}
......@@ -371,9 +382,6 @@ class LanguageService
return $this->languageFileCache[$fileRef . $this->lang];
}
/** @var LocalizationFactory $languageFactory */
$languageFactory = GeneralUtility::makeInstance(LocalizationFactory::class);
if ($this->lang !== 'default') {
$languages = array_reverse($this->languageDependencies);
} else {
......@@ -381,7 +389,7 @@ class LanguageService
}
$localLanguage = [];
foreach ($languages as $language) {
$tempLL = $languageFactory->getParsedData($fileRef, $language);
$tempLL = $this->localizationFactory->getParsedData($fileRef, $language);
$localLanguage['default'] = $tempLL['default'];
if (!isset($localLanguage[$this->lang])) {
$localLanguage[$this->lang] = $localLanguage['default'];
......@@ -435,9 +443,7 @@ class LanguageService
*/
public static function create(string $locale): self
{
$obj = GeneralUtility::makeInstance(LanguageService::class);
$obj->init($locale);
return $obj;
return GeneralUtility::makeInstance(LanguageServiceFactory::class)->create($locale);
}
public static function createFromUserPreferences(?AbstractUserAuthentication $user): self
......
<?php
declare(strict_types=1);
/*
* 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!
*/
namespace TYPO3\CMS\Core\Localization;
/**
* @internal
*/
class LanguageServiceFactory
{
/**
* @var Locales
*/
protected $locales;
/**
* @var LocalizationFactory
*/
protected $localizationFactory;
public function __construct(Locales $locales, LocalizationFactory $localizationFactory)
{
$this->locales = $locales;
$this->localizationFactory = $localizationFactory;
}
/**
* Factory method to create a language service object.
*
* @param string $locale the locale (= the TYPO3-internal locale given)
* @return LanguageService
*/
public function create(string $locale): LanguageService
{
$obj = new LanguageService($this->locales, $this->localizationFactory);
$obj->init($locale);
return $obj;
}
}
......@@ -36,21 +36,10 @@ class LocalizationFactory implements SingletonInterface
*/
public $store;
/**
* Class constructor
*/
public function __construct()
{
$this->store = GeneralUtility::makeInstance(LanguageStore::class);
$this->initializeCache();
}
/**
* Initialize cache instance to be ready to use
*/
protected function initializeCache()
public function __construct(LanguageStore $languageStore, CacheManager $cacheManager)
{
$this->cacheInstance = GeneralUtility::makeInstance(CacheManager::class)->getCache('l10n');
$this->store = $languageStore;
$this->cacheInstance = $cacheManager->getCache('l10n');
}
/**
......
......@@ -20,6 +20,7 @@ namespace TYPO3\CMS\Core;
use ArrayObject;
use Psr\Container\ContainerInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Package\AbstractServiceProvider;
/**
......@@ -36,15 +37,37 @@ class ServiceProvider extends AbstractServiceProvider
{
return [
Cache\CacheManager::class => [ static::class, 'getCacheManager' ],
Charset\CharsetConverter::class => [ static::class, 'getCharsetConverter' ],
Configuration\SiteConfiguration::class => [ static::class, 'getSiteConfiguration' ],
Console\CommandApplication::class => [ static::class, 'getConsoleCommandApplication' ],
Console\CommandRegistry::class => [ static::class, 'getConsoleCommandRegistry' ],
Context\Context::class => [ static::class, 'getContext' ],
Crypto\PasswordHashing\PasswordHashFactory::class => [ static::class, 'getPasswordHashFactory' ],
EventDispatcher\EventDispatcher::class => [ static::class, 'getEventDispatcher' ],
EventDispatcher\ListenerProvider::class => [ static::class, 'getEventListenerProvider' ],
Http\MiddlewareStackResolver::class => [ static::class, 'getMiddlewareStackResolver' ],
Service\DependencyOrderingService::class => [ static::class, 'getDependencyOrderingService' ],
Crypto\PasswordHashing\PasswordHashFactory::class => [ static::class, 'getPasswordHashFactory' ],
Http\RequestFactory::class => [ static::class, 'getRequestFactory' ],
Imaging\IconFactory::class => [ static::class, 'getIconFactory' ],
Imaging\IconRegistry::class => [ static::class, 'getIconRegistry' ],
Localization\LanguageServiceFactory::class => [ static::class, 'getLanguageServiceFactory' ],
Localization\LanguageStore::class => [ static::class, 'getLanguageStore' ],
Localization\Locales::class => [ static::class, 'getLocales' ],
Localization\LocalizationFactory::class => [ static::class, 'getLocalizationFactory' ],
Mail\TransportFactory::class => [ static::class, 'getMailTransportFactory' ],
Messaging\FlashMessageService::class => [ static::class, 'getFlashMessageService' ],
Package\FailsafePackageManager::class => [ static::class, 'getFailsafePackageManager' ],
Registry::class => [ static::class, 'getRegistry' ],
Resource\Index\FileIndexRepository::class => [ static::class, 'getFileIndexRepository' ],
Resource\Driver\DriverRegistry::class => [ static::class, 'getDriverRegistry' ],
Resource\ProcessedFileRepository::class => [ static::class, 'getProcessedFileRepository' ],
Resource\ResourceFactory::class => [ static::class, 'getResourceFactory' ],
Resource\StorageRepository::class => [ static::class, 'getStorageRepository' ],
Service\DependencyOrderingService::class => [ static::class, 'getDependencyOrderingService' ],
Service\FlexFormService::class => [ static::class, 'getFlexFormService' ],
Service\OpcodeCacheService::class => [ static::class, 'getOpcodeCacheService' ],
TimeTracker\TimeTracker::class => [ static::class, 'getTimeTracker' ],
TypoScript\Parser\ConstantConfigurationParser::class => [ static::class, 'getTypoScriptConstantConfigurationParser' ],
TypoScript\TypoScriptService::class => [ static::class, 'getTypoScriptService' ],
'middlewares' => [ static::class, 'getMiddlewares' ],
];
}
......@@ -81,6 +104,16 @@ class ServiceProvider extends AbstractServiceProvider
return $cacheManager;
}
public static function getCharsetConverter(ContainerInterface $container): Charset\CharsetConverter
{
return self::new($container, Charset\CharsetConverter::class);
}
public static function getSiteConfiguration(ContainerInterface $container): Configuration\SiteConfiguration
{
return new Configuration\SiteConfiguration(Environment::getConfigPath() . '/sites');
}
public static function getConsoleCommandApplication(ContainerInterface $container): Console\CommandApplication
{
return new Console\CommandApplication(
......@@ -118,11 +151,6 @@ class ServiceProvider extends AbstractServiceProvider
return $listenerProvider;
}
public static function getDependencyOrderingService(ContainerInterface $container): Service\DependencyOrderingService
{
return new Service\DependencyOrderingService();
}
public static function getContext(ContainerInterface $container): Context\Context
{
return new Context\Context();
......@@ -133,13 +161,84 @@ class ServiceProvider extends AbstractServiceProvider
return new Crypto\PasswordHashing\PasswordHashFactory();
}
public static function getMiddlewareStackResolver(ContainerInterface $container): Http\MiddlewareStackResolver
public static function getIconFactory(ContainerInterface $container): Imaging\IconFactory
{
return new Http\MiddlewareStackResolver(
$container,
$container->get(Service\DependencyOrderingService::class),
$container->get('cache.core')
);
return self::new($container, Imaging\IconFactory::class, [
$container->get(EventDispatcherInterface::class),
$container->get(Imaging\IconRegistry::class)
]);
}
public static function getIconRegistry(ContainerInterface $container): Imaging\IconRegistry
{
return self::new($container, Imaging\IconRegistry::class);
}
public static function getLanguageServiceFactory(ContainerInterface $container): Localization\LanguageServiceFactory
{
return self::new($container, Localization\LanguageServiceFactory::class, [
$container->get(Localization\Locales::class),
$container->get(Localization\LocalizationFactory::class)
]);
}
public static function getLanguageStore(ContainerInterface $container): Localization\LanguageStore
{
return self::new($container, Localization\LanguageStore::class);
}
public static function getLocales(ContainerInterface $container): Localization\Locales
{
return self::new($container, Localization\Locales::class);
}
public static function getLocalizationFactory(ContainerInterface $container): Localization\LocalizationFactory
{
return self::new($container, Localization\LocalizationFactory::class, [
$container->get(Localization\LanguageStore::class),
$container->get(Cache\CacheManager::class)
]);
}
public static function getMailTransportFactory(ContainerInterface $container): Mail\TransportFactory
{
return self::new($container, Mail\TransportFactory::class);
}
public static function getFlashMessageService(ContainerInterface $container): Messaging\FlashMessageService
{
return self::new($container, Messaging\FlashMessageService::class);
}
public static function getFailsafePackageManager(ContainerInterface $container): Package\FailsafePackageManager
{
$packageManager = $container->get(Package\PackageManager::class);
if ($packageManager instanceof Package\FailsafePackageManager) {
return $packageManager;
}
throw new \RuntimeException('FailsafePackageManager can only be instantiated in failsafe (maintenance tool) mode.', 1586861816);
}
public static function getRegistry(ContainerInterface $container): Registry
{
return self::new($container, Registry::class);
}
public static function getFileIndexRepository(ContainerInterface $container): Resource\Index\FileIndexRepository
{
return self::new($container, Resource\Index\FileIndexRepository::class, [
$container->get(EventDispatcherInterface::class)
]);
}
public static function getDriverRegistry(ContainerInterface $container): Resource\Driver\DriverRegistry
{
return self::new($container, Resource\Driver\DriverRegistry::class);
}
public static function getProcessedFileRepository(ContainerInterface $container): Resource\ProcessedFileRepository
{
return self::new($container, Resource\ProcessedFileRepository::class);
}
public static function getResourceFactory(ContainerInterface $container): Resource\ResourceFactory
......@@ -149,6 +248,55 @@ class ServiceProvider extends AbstractServiceProvider
]);
}
public static function getStorageRepository(ContainerInterface $container): Resource\StorageRepository
{
return self::new($container, Resource\StorageRepository::class);
}
public static function getDependencyOrderingService(ContainerInterface $container): Service\DependencyOrderingService
{
return new Service\DependencyOrderingService();
}
public static function getFlexFormService(ContainerInterface $container): Service\FlexFormService
{
return self::new($container, Service\FlexFormService::class);
}
public static function getOpcodeCacheService(ContainerInterface $container): Service\OpcodeCacheService
{
return self::new($container, Service\OpcodeCacheService::class);
}
public static function getTimeTracker(ContainerInterface $container): TimeTracker\TimeTracker
{
return self::new($container, TimeTracker\TimeTracker::class);
}
public static function getTypoScriptConstantConfigurationParser(ContainerInterface $container): TypoScript\Parser\ConstantConfigurationParser
{
return self::new($container, TypoScript\Parser\ConstantConfigurationParser::class);
}
public static function getTypoScriptService(ContainerInterface $container): TypoScript\TypoScriptService
{
return self::new($container, TypoScript\TypoScriptService::class);
}
public static function getRequestFactory(ContainerInterface $container): Http\RequestFactory
{
return new Http\RequestFactory();
}
public static function getMiddlewareStackResolver(ContainerInterface $container): Http\MiddlewareStackResolver
{
return new Http\MiddlewareStackResolver(
$container,
$container->get(Service\DependencyOrderingService::class),
$container->get('cache.core')
);
}
public static function getMiddlewares(ContainerInterface $container): ArrayObject
{
return new ArrayObject();
......
......@@ -56,9 +56,6 @@ services:
arguments:
$configPath: "%env(TYPO3:configPath)%/sites"
TYPO3\CMS\Core\Package\FailsafePackageManager:
autoconfigure: false
TYPO3\CMS\Core\Package\UnitTestPackageManager:
autoconfigure: false
......@@ -321,6 +318,15 @@ services:
method: 'addCategoryDatabaseSchema'
event: TYPO3\CMS\Core\Database\Event\AlterTableDefinitionStatementsEvent
# @internal
# @todo: deprecate makeInstance(LanguageService::class)
# This service entry is provided for legacy code that instantiates LanguageService
# using GeneralUtility::makeInstance instead of the factory methods which itself
# use LanguageServiceFactory (for install tool compatibility).
TYPO3\CMS\Core\Localization\LanguageService:
shared: false
public: true
TYPO3\CMS\Core\Page\AssetRenderer:
public: true
arguments:
......
......@@ -32,7 +32,7 @@ class QueryGeneratorTest extends FunctionalTestCase
{
parent::setUp();
$this->setUpBackendUserFromFixture(1);
$GLOBALS['LANG'] = new LanguageService();
$GLOBALS['LANG'] = LanguageService::create('default');
}
/**
......
......@@ -943,8 +943,6 @@ class DataHandlerTest extends UnitTestCase
*/
public function checkValueForInputConvertsNullToEmptyString()
{
$GLOBALS['LANG'] = GeneralUtility::makeInstance(LanguageService::class);
$GLOBALS['LANG']->init('default');
$expectedResult = ['value' => ''];
self::assertSame($expectedResult, $this->subject->_call('checkValueForInput', null, ['type' => 'string', 'max' => 40], 'tt_content', 'NEW55c0e67f8f4d32.04974534', 89, 'table_caption'));
}
......
......@@ -18,6 +18,7 @@ namespace TYPO3\CMS\Core\Tests\Unit\Error;
use Prophecy\Argument;
use Psr\Log\LoggerInterface;
use TYPO3\CMS\Core\Error\ProductionExceptionHandler;
use TYPO3\CMS\Core\Information\Typo3Information;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
......@@ -51,6 +52,9 @@ class ProductionExceptionHandlerTest extends UnitTestCase
*/
public function echoExceptionWebEscapesExceptionMessage()
{
$typo3InformationProphecy = $this->prophesize(Typo3Information::class);
$typo3InformationProphecy->getCopyrightYear()->willReturn('1999-20XX');
GeneralUtility::addInstance(Typo3Information::class, $typo3InformationProphecy->reveal());
$message = '<b>b</b><script>alert(1);</script>';
$exception = new \Exception($message, 1476049364);
ob_start();
......@@ -66,6 +70,9 @@ class ProductionExceptionHandlerTest extends UnitTestCase
*/
public function echoExceptionWebEscapesExceptionTitle()
{
$typo3InformationProphecy = $this->prophesize(Typo3Information::class);
$typo3InformationProphecy->getCopyrightYear()->willReturn('1999-20XX');
GeneralUtility::addInstance(Typo3Information::class, $typo3InformationProphecy->reveal());
$title = '<b>b</b><script>alert(1);</script>';
/** @var $exception \Exception|\PHPUnit\Framework\MockObject\MockObject */
$exception = $this->getMockBuilder('Exception')
......@@ -120,6 +127,9 @@ class ProductionExceptionHandlerTest extends UnitTestCase
*/
public function logEntriesContainAnonymousTokens(string $originalUrl, string $expectedUrl)
{
$typo3InformationProphecy = $this->prophesize(Typo3Information::class);
$typo3InformationProphecy->getCopyrightYear()->willReturn('1999-20XX');
GeneralUtility::addInstance(Typo3Information::class, $typo3InformationProphecy->reveal());
$subject = new ProductionExceptionHandler();
$logger = $this->prophesize(LoggerInterface::class);
$logger->critical(Argument::containingString($expectedUrl), Argument::cetera())->shouldBeCalled();
......
......@@ -21,6 +21,7 @@ use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Imaging\IconRegistry;
use TYPO3\CMS\Core\Type\Icon\IconState;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
......@@ -58,7 +59,7 @@ class IconTest extends UnitTestCase
$cacheFrontendProphecy->get(Argument::cetera())->willReturn(false);
$cacheFrontendProphecy->set(Argument::cetera())->willReturn(null);
$eventDispatcherProphecy = $this->prophesize(EventDispatcherInterface::class);
$iconFactory = new IconFactory($eventDispatcherProphecy->reveal());
$iconFactory = new IconFactory($eventDispatcherProphecy->reveal(), new IconRegistry());
$this->subject = $iconFactory->getIcon($this->iconIdentifier, Icon::SIZE_SMALL, $this->overlayIdentifier, IconState::cast(IconState::STATE_DISABLED));
}
......
......@@ -20,7 +20,6 @@ use TYPO3\CMS\Core\Cache\Frontend\VariableFrontend;
use TYPO3\CMS\Core\Localization\Exception\FileNotFoundException;
use TYPO3\CMS\Core\Localization\LanguageStore;
use TYPO3\CMS\Core\Localization\LocalizationFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
/**
......@@ -28,21 +27,11 @@ use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
*/
class LocalizationFactoryTest extends UnitTestCase
{
public function tearDown(): void
{
// Drop created singletons again
GeneralUtility::purgeInstances();
parent::tearDown();
}
/**
* @test
*/
public function getParsedDataCallsLocalizationOverrideIfFileNotFoundExceptionIsThrown()
{
$cacheManagerProphecy = $this->prophesize(CacheManager::class);
GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
$languageStore = $this->getMockBuilder(LanguageStore::class)
->onlyMethods(['hasData', 'setConfiguration', 'getData', 'setData'])
->getMock();
......@@ -50,14 +39,16 @@ class LocalizationFactoryTest extends UnitTestCase
->onlyMethods(['get', 'set'])
->disableOriginalConstructor()
->getMock();
$cacheManagerProphecy->getCache('l10n')->willReturn($cacheInstance);
$localizationFactory = new LocalizationFactory();
$localizationFactory->store = $languageStore;
$languageStore->method('hasData')->willReturn(false);
$languageStore->method('getData')->willReturn(['default' => []]);
$languageStore->method('setConfiguration')->willThrowException(new FileNotFoundException('testing', 1476049512));
$cacheInstance->method('get')->willReturn(false);
$cacheManagerProphecy = $this->prophesize(CacheManager::class);
$cacheManagerProphecy->getCache('l10n')->willReturn($cacheInstance);
/** @var $localizationFactory LocalizationFactory */
$localizationFactory = $this->getAccessibleMock(LocalizationFactory::class, ['localizationOverride'], [$languageStore, $cacheManagerProphecy->reveal()]);
$GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride'] = ['foo' => 'bar'];
$localizationFactory->getParsedData('EXT:backend/Resources/Private/Language/locallang_layout.xlf', 'default');
......
......@@ -19,9 +19,9 @@ use Prophecy\Argument;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Localization\LanguageStore;
use TYPO3\CMS\Core\Localization\LocalizationFactory;
use TYPO3\CMS\Core\Localization\Parser\XliffParser;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
/**
......@@ -34,6 +34,11 @@ class XliffParserTest extends UnitTestCase
*/
protected $xliffFileNames;
/**
* @var ObjectProphecy|CacheManager
*/
protected $cacheManagerProphecy;
/**
* Prepares the environment before running a test.
*/
......@@ -49,24 +54,15 @@ class XliffParserTest extends UnitTestCase
];
$GLOBALS['TYPO3_CONF_VARS']['SYS']['lang']['format']['priority'] = 'xlf';
$cacheManagerProphecy = $this->prophesize(CacheManager::class);
GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
$this->languageStoreProphecy = $this->prophesize(LanguageStore::class);
$this->cacheManagerProphecy = $this->prophesize(CacheManager::class);
$cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
$cacheManagerProphecy->getCache('l10n')->willReturn($cacheFrontendProphecy->reveal());
$this->cacheManagerProphecy->getCache('l10n')->willReturn($cacheFrontendProphecy->reveal());
$cacheFrontendProphecy->get(Argument::cetera())->willReturn(false);
$cacheFrontendProphecy->set(Argument::cetera())->willReturn(null);
$cacheFrontendProphecy->flush()->willReturn(null);
}
/**