Commit fe09b372 authored by crell's avatar crell
Browse files

[TASK] Convert Environment class to an injectable object.

This is step one in unwinding the Environment class.  It moves to
an object stored in a static variable, and everything is built
off of that.  I included one example of how the new-style will
be used.  Converting the zillion other uses will be follow-up
issues.  The static methods should also get marked deprecated
to point people toward the object properties.

Resolves: #94995
Releases: master
Change-Id: I620d8e690e9adc03a7dae4b0b83541be9bcd788b
parent d84b0641
Pipeline #22362 failed with stages
in 6 minutes and 40 seconds
......@@ -69,6 +69,11 @@ class StandardContentPreviewRenderer implements PreviewRendererInterface, Logger
'menu_subpages',
];
public function __construct(
protected readonly Environment $environment,
) {
}
public function renderPageModulePreviewHeader(GridColumnItem $item): string
{
$record = $item->getRecord();
......@@ -334,8 +339,8 @@ class StandardContentPreviewRenderer implements PreviewRendererInterface, Logger
if ($GLOBALS['TYPO3_CONF_VARS']['BE']['debug'] && $this->getBackendUser()->isAdmin()) {
$view = GeneralUtility::makeInstance(StandaloneView::class);
$view->assign('error', [
'message' => str_replace(Environment::getProjectPath(), '', $e->getMessage()),
'title' => 'Error while rendering FluidTemplate preview using ' . str_replace(Environment::getProjectPath(), '', $fluidTemplateFile),
'message' => str_replace($this->environment->projectPath, '', $e->getMessage()),
'title' => 'Error while rendering FluidTemplate preview using ' . str_replace($this->environment->projectPath, '', $fluidTemplateFile),
]);
$view->setTemplateSource('<f:be.infobox title="{error.title}" state="2">{error.message}</f:be.infobox>');
return $view->render();
......
......@@ -17,6 +17,7 @@ declare(strict_types=1);
namespace TYPO3\CMS\Backend\Preview;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
......@@ -33,6 +34,11 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
*/
class StandardPreviewRendererResolver implements PreviewRendererResolverInterface
{
public function __construct(
protected readonly Environment $environment,
) {
}
/**
* @param string $table The name of the table the returned PreviewRenderer must work with
* @param array $row A record from $table which will be previewed - allows returning a different PreviewRenderer based on record attributes
......@@ -86,7 +92,7 @@ class StandardPreviewRendererResolver implements PreviewRendererResolverInterfac
1477512798
);
}
return GeneralUtility::makeInstance($previewRendererClassName);
return GeneralUtility::makeInstance($previewRendererClassName, $this->environment);
}
throw new \RuntimeException(sprintf('No Preview renderer registered for table %s', $table), 1477520356);
}
......
......@@ -16,6 +16,6 @@
// Set up the application for the backend
call_user_func(static function () {
$classLoader = require __DIR__ . '/../../../../../../vendor/autoload.php';
\TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::run(1, \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_BE);
\TYPO3\CMS\Core\Core\Bootstrap::init($classLoader)->get(\TYPO3\CMS\Backend\Http\Application::class)->run();
$env = \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::run(1, \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_BE);
\TYPO3\CMS\Core\Core\Bootstrap::init($classLoader, $env)->get(\TYPO3\CMS\Backend\Http\Application::class)->run();
});
......@@ -20,6 +20,7 @@ namespace TYPO3\CMS\Backend\Tests\Unit\Preview;
use TYPO3\CMS\Backend\Preview\PreviewRendererInterface;
use TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer;
use TYPO3\CMS\Backend\Preview\StandardPreviewRendererResolver;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Domain\Repository\PageRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
......@@ -32,7 +33,9 @@ class StandardPreviewRendererResolverTest extends UnitTestCase
{
parent::setUp();
$this->subject = new StandardPreviewRendererResolver();
$env = Environment::instance();
$this->subject = new StandardPreviewRendererResolver($env);
$GLOBALS['TCA']['tt_content'] = [
'ctrl' => [
'type' => 'CType',
......
......@@ -77,12 +77,13 @@ class Bootstrap
*/
public static function init(
ClassLoader $classLoader,
bool $failsafe = false
Environment $environment,
bool $failsafe = false,
): ContainerInterface {
$requestId = new RequestId();
static::initializeClassLoader($classLoader);
if (!Environment::isComposerMode() && ClassLoadingInformation::isClassLoadingInformationAvailable()) {
if (!$environment->composerMode && ClassLoadingInformation::isClassLoadingInformationAvailable()) {
ClassLoadingInformation::registerClassLoadingInformation();
}
......@@ -124,6 +125,7 @@ class Bootstrap
$builder = new ContainerBuilder([
ClassLoader::class => $classLoader,
ApplicationContext::class => Environment::getContext(),
Environment::class => $environment,
ConfigurationManager::class => $configurationManager,
LogManager::class => $logManager,
RequestId::class => $requestId,
......
......@@ -51,70 +51,33 @@ class Environment
'srv', // HHVM with fastcgi
];
/**
* @var bool
*/
protected static $cli;
/**
* @var bool
*/
protected static $composerMode;
/**
* @var ApplicationContext
*/
protected static $context;
/**
* @var string
*/
protected static $projectPath;
/**
* @var string
*/
protected static $composerRootPath;
/**
* @var string
*/
protected static $publicPath;
/**
* @var string
*/
protected static $currentScript;
/**
* @var string
*/
protected static $os;
/**
* @var string
*/
protected static $varPath;
/**
* @var string
*/
protected static $configPath;
protected static self $environment;
public readonly string $composerRootPath;
public function __construct(
public readonly bool $cli,
public readonly bool $composerMode,
public readonly ApplicationContext $context,
public readonly string $projectPath,
public readonly string $publicPath,
public readonly string $currentScript,
public readonly string $os,
public readonly string $varPath,
public readonly string $configPath,
) {
$this->composerRootPath = $composerMode
? PathUtility::getCanonicalPath(InstalledVersions::getRootPackage()['install_path'])
: '';
}
/**
* Sets up the Environment. Please note that this is not public API and only used within the very early
* Set up of TYPO3, or to be used within tests. If you ever call this method in your extension, you're probably
* Sets up the Environment.
*
* Please note that this is not public API and only used within the very early
* set up of TYPO3, or to be used within tests. If you ever call this method in your extension, you're probably
* doing something wrong. Never call this method! Never rely on it!
*
* @param ApplicationContext $context
* @param bool $cli
* @param bool $composerMode
* @param string $projectPath
* @param string $publicPath
* @param string $varPath
* @param string $configPath
* @param string $currentScript
* @param string $os
* @internal
*/
public static function initialize(
......@@ -126,18 +89,35 @@ class Environment
string $varPath,
string $configPath,
string $currentScript,
string $os
) {
self::$cli = $cli;
self::$composerMode = $composerMode;
self::$context = $context;
self::$projectPath = $projectPath;
self::$composerRootPath = $composerMode ? PathUtility::getCanonicalPath(InstalledVersions::getRootPackage()['install_path']) : '';
self::$publicPath = $publicPath;
self::$varPath = $varPath;
self::$configPath = $configPath;
self::$currentScript = $currentScript;
self::$os = $os;
string $os,
): self {
return self::$environment = new self(
cli: $cli,
composerMode: $composerMode,
context: $context,
projectPath: $projectPath,
publicPath: $publicPath,
currentScript: $currentScript,
os: $os,
varPath: $varPath,
configPath: $configPath,
);
}
/**
* Returns the currently active instance.
*
* This is a temporary hack to allow the environment to be injected
* into the container. It is not part of an API guarantee. Do not use it.
* It may disappear without warning at any time.
*
* @internal
*
* @return self
*/
public static function instance(): self
{
return self::$environment;
}
/**
......@@ -149,7 +129,7 @@ class Environment
*/
public static function getContext(): ApplicationContext
{
return self::$context;
return self::$environment->context;
}
/**
......@@ -160,7 +140,7 @@ class Environment
*/
public static function isComposerMode(): bool
{
return self::$composerMode;
return self::$environment->composerMode;
}
/**
......@@ -170,7 +150,7 @@ class Environment
*/
public static function isCli(): bool
{
return self::$cli;
return self::$environment->cli;
}
/**
......@@ -185,7 +165,7 @@ class Environment
*/
public static function getProjectPath(): string
{
return self::$projectPath;
return self::$environment->projectPath;
}
/**
......@@ -199,11 +179,11 @@ class Environment
*/
public static function getComposerRootPath(): string
{
if (self::$composerMode === false) {
if (self::$environment->composerMode === false) {
throw new \BadMethodCallException('Composer root path is only available in Composer mode', 1631700480);
}
return self::$composerRootPath;
return self::$environment->composerRootPath;
}
/**
......@@ -214,7 +194,7 @@ class Environment
*/
public static function getPublicPath(): string
{
return self::$publicPath;
return self::$environment->publicPath;
}
/**
......@@ -226,7 +206,7 @@ class Environment
*/
public static function getVarPath(): string
{
return self::$varPath;
return self::$environment->varPath;
}
/**
......@@ -244,7 +224,7 @@ class Environment
*/
public static function getConfigPath(): string
{
return self::$configPath;
return self::$environment->configPath;
}
/**
......@@ -254,7 +234,7 @@ class Environment
*/
public static function getCurrentScript(): string
{
return self::$currentScript;
return self::$environment->currentScript;
}
/**
......@@ -270,7 +250,7 @@ class Environment
*/
public static function getLabelsPath(): string
{
if (self::$publicPath === self::$projectPath) {
if (self::$environment->publicPath === self::$environment->projectPath) {
return self::getPublicPath() . '/typo3conf/l10n';
}
return self::getVarPath() . '/labels';
......@@ -287,6 +267,11 @@ class Environment
return self::getPublicPath() . '/typo3';
}
public function backendPath(): string
{
return $this->publicPath . '/typo3';
}
/**
* Previously known as PATH_typo3 . 'sysext/'
* Please note that this might be gone at some point
......@@ -326,7 +311,7 @@ class Environment
*/
public static function isWindows(): bool
{
return self::$os === 'WINDOWS';
return self::$environment->os === 'WINDOWS';
}
/**
......@@ -336,7 +321,7 @@ class Environment
*/
public static function isUnix(): bool
{
return self::$os === 'UNIX';
return self::$environment->os === 'UNIX';
}
/**
......@@ -357,13 +342,13 @@ class Environment
public static function toArray(): array
{
return [
'context' => (string)self::getContext(),
'cli' => self::isCli(),
'projectPath' => self::getProjectPath(),
'publicPath' => self::getPublicPath(),
'varPath' => self::getVarPath(),
'configPath' => self::getConfigPath(),
'currentScript' => self::getCurrentScript(),
'context' => (string)self::$environment->context,
'cli' => self::$environment->cli,
'projectPath' => self::$environment->projectPath,
'publicPath' => self::$environment->publicPath,
'varPath' => self::$environment->varPath,
'configPath' => self::$environment->configPath,
'currentScript' => self::$environment->currentScript,
'os' => self::isWindows() ? 'WINDOWS' : 'UNIX',
];
}
......
......@@ -58,7 +58,7 @@ class SystemEnvironmentBuilder
* @param int $entryPointLevel Number of subdirectories where the entry script is located under the document root
* @param int $requestType
*/
public static function run(int $entryPointLevel = 0, int $requestType = self::REQUESTTYPE_FE)
public static function run(int $entryPointLevel = 0, int $requestType = self::REQUESTTYPE_FE): Environment
{
self::defineBaseConstants();
$scriptPath = self::calculateScriptPath($entryPointLevel, $requestType);
......@@ -66,7 +66,7 @@ class SystemEnvironmentBuilder
self::initializeGlobalVariables();
self::initializeGlobalTimeTrackingVariables();
self::initializeEnvironment($requestType, $scriptPath, $rootPath);
return self::initializeEnvironment($requestType, $scriptPath, $rootPath);
}
/**
......@@ -199,7 +199,7 @@ class SystemEnvironmentBuilder
* @param string $scriptPath
* @param string $sitePath
*/
protected static function initializeEnvironment(int $requestType, string $scriptPath, string $sitePath)
protected static function initializeEnvironment(int $requestType, string $scriptPath, string $sitePath): Environment
{
if (getenv('TYPO3_PATH_ROOT')) {
$rootPathFromEnvironment = rtrim(GeneralUtility::fixWindowsFilePath((string)getenv('TYPO3_PATH_ROOT')), '/');
......@@ -214,7 +214,7 @@ class SystemEnvironmentBuilder
$projectRootPath = GeneralUtility::fixWindowsFilePath((string)getenv('TYPO3_PATH_APP'));
$isDifferentRootPath = ($projectRootPath && $projectRootPath !== $sitePath);
Environment::initialize(
return Environment::initialize(
static::createApplicationContext(),
self::isCliRequestType($requestType),
static::usesComposerClassLoading(),
......
......@@ -19,6 +19,6 @@
*/
call_user_func(static function () {
$classLoader = require __DIR__ . '/../../../../../../vendor/autoload.php';
\TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::run(4, \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_CLI);
\TYPO3\CMS\Core\Core\Bootstrap::init($classLoader, true)->get(\TYPO3\CMS\Core\Console\CommandApplication::class)->run();
$env = \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::run(4, \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_CLI);
\TYPO3\CMS\Core\Core\Bootstrap::init($classLoader, $env, true)->get(\TYPO3\CMS\Core\Console\CommandApplication::class)->run();
});
......@@ -331,12 +331,11 @@ class InstallUtilityTest extends UnitTestCase
$subject->injectRegistry($registry->reveal());
// provide function result inside test output folder
$environment = new Environment();
$configDir = $absPath . 'Result/config';
if (!file_exists($configDir)) {
GeneralUtility::mkdir_deep($configDir);
}
$environment::initialize(
Environment::initialize(
Environment::getContext(),
Environment::isCli(),
Environment::isComposerMode(),
......@@ -402,9 +401,7 @@ class InstallUtilityTest extends UnitTestCase
$registry->set('siteConfigImport', Argument::cetera())->shouldNotBeCalled();
$subject->injectRegistry($registry->reveal());
$environment = new Environment();
$environment::initialize(
Environment::initialize(
Environment::getContext(),
Environment::isCli(),
Environment::isComposerMode(),
......
......@@ -16,6 +16,6 @@
// Set up the application for the frontend
call_user_func(static function () {
$classLoader = require __DIR__ . '/../../../../../../vendor/autoload.php';
\TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::run(0, \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_FE);
\TYPO3\CMS\Core\Core\Bootstrap::init($classLoader)->get(\TYPO3\CMS\Frontend\Http\Application::class)->run();
$env = \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::run(0, \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_FE);
\TYPO3\CMS\Core\Core\Bootstrap::init($classLoader, $env)->get(\TYPO3\CMS\Frontend\Http\Application::class)->run();
});
......@@ -95,6 +95,6 @@
*/
call_user_func(static function () {
$classLoader = require __DIR__ . '/../../../../../../vendor/autoload.php';
\TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::run(1, \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_INSTALL);
\TYPO3\CMS\Core\Core\Bootstrap::init($classLoader, true)->get(\TYPO3\CMS\Install\Http\Application::class)->run();
$env = \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::run(1, \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_INSTALL);
\TYPO3\CMS\Core\Core\Bootstrap::init($classLoader, $env, true)->get(\TYPO3\CMS\Install\Http\Application::class)->run();
});
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment