Skip to content

Commit

Permalink
[TASK] Decouple Bootstrap and Application engaging a PSR-11 container
Browse files Browse the repository at this point in the history
In order to avoid global state and to support full-application
subrequests (later on), bootstraping, application initialization
and application execution needs to be decoupled.
(To be able to initialize a frontend Application in backend
Application context, the frontend Application may not re-execute
bootstraping code.)

That means from now on:
 * Bootstrap is limited to stateless bootstrapping
   => setting up package manager and configuration
 * A (new) Container (PSR-11) performs class initialization
   => e.g. `new Frontend/Http/Application()`
 * Application performs execution
   => checking possible (application specific) redirects
   => offloading work to the request handler

This commit transforms Bootstrap into a (static) bootstrap utility
that returns a container (minimal, static PSR-11 implementation).
The entry-point scripts execute the bootstraper and use
the returned container to initialize and run the application.

This commit acts as a starting point for a broader PSR-11 container
support in TYPO3. We do – on purpose – use an own, very limited, anonymous
and static there is no configuration) PSR-11 implemententation for now.
This interim container implementation will be replaced by whatever
PSR-11 supporting container solution we use later on.
That keeps the necessary Bootstrap refactoring seperate from the
introduction of a full dependency injection container implementation.

All existing bootstrap methods keep working as before but the non-static
method invocation should be deprecated at some point.

typo3/cms-cli is adapted for the changed entry point script with:
TYPO3/cms-cli#1

typo3/testing-framework is adapted in
TYPO3/testing-framework#55

This patch brings one important behavioral change:

The install tool redirect (if essential configuration is missing) is
perfomed during application execution – after the configuration has been
loaded (falling back to failsafe mode if missing) – now. Previously the
application performed the redirect before it would call Bootstraps
configure() method. Now that the Application is decoupled from bootstrap,
the bootstrapper ensures it can always create an Application class, in
order for the application to be in charge of the decision what should
happen if essential configuration is missing.

Dependency changes:

composer require psr/container:^1.0
composer require typo3/cms-cli:^2.0
composer require typo3/testing-framework:^3.2 --dev

Change-Id: Idc59665dfcf7250a8a42b3d908a5a2376067700c
Releases: master
Resolves: #83951
Reviewed-on: https://review.typo3.org/55773
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
  • Loading branch information
bnf authored and bmack committed Mar 8, 2018
1 parent d6ff441 commit a388232
Show file tree
Hide file tree
Showing 15 changed files with 545 additions and 277 deletions.
7 changes: 4 additions & 3 deletions composer.json
Expand Up @@ -43,7 +43,7 @@
"symfony/polyfill-mbstring": "^1.2",
"doctrine/instantiator": "~1.0.4",
"doctrine/annotations": "^1.3",
"typo3/cms-cli": "^1.0",
"typo3/cms-cli": "^2.0",
"typo3/class-alias-loader": "^1.0",
"typo3/cms-composer-installers": "^2.0",
"psr/http-message": "~1.0",
Expand All @@ -54,15 +54,16 @@
"doctrine/dbal": "^2.6",
"nikic/php-parser": "^3.1",
"symfony/polyfill-intl-icu": "^1.6",
"psr/http-server-middleware": "^1.0"
"psr/http-server-middleware": "^1.0",
"psr/container": "^1.0"
},
"require-dev": {
"codeception/codeception": "^2.3",
"enm1989/chromedriver": "~2.30",
"friendsofphp/php-cs-fixer": "^2.0",
"fiunchinho/phpunit-randomizer": "~3.0.0",
"typo3/cms-styleguide": "~9.0.1",
"typo3/testing-framework": "^3.0"
"typo3/testing-framework": "^3.2"
},
"suggest": {
"ext-gd": "GDlib/Freetype is required for building images with text (GIFBUILDER) and can also be used to scale images",
Expand Down
93 changes: 68 additions & 25 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 21 additions & 29 deletions typo3/sysext/backend/Classes/Http/Application.php
Expand Up @@ -16,7 +16,8 @@
*/

use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\Core\Bootstrap;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Configuration\ConfigurationManager;
use TYPO3\CMS\Core\Http\AbstractApplication;
use TYPO3\CMS\Core\Http\RedirectResponse;

Expand All @@ -36,46 +37,38 @@ class Application extends AbstractApplication
protected $middlewareStack = 'backend';

/**
* @var Bootstrap
* @var ConfigurationManager
*/
protected $bootstrap;
protected $configurationManager;

/**
* Number of subdirectories where the entry script is located, relative to PATH_site
* Usually this is equal to PATH_site = 0
* @var int
* @param ConfigurationManager $configurationManager
*/
protected $entryPointLevel = 1;
public function __construct(ConfigurationManager $configurationManager)
{
$this->configurationManager = $configurationManager;
}

/**
* Constructor setting up legacy constant and register available Request Handlers
*
* @param \Composer\Autoload\ClassLoader $classLoader an instance of the class loader
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
public function __construct($classLoader)
protected function handle(ServerRequestInterface $request): ResponseInterface
{
$this->defineLegacyConstants();

$this->bootstrap = Bootstrap::getInstance()
->initializeClassLoader($classLoader)
->setRequestType(TYPO3_REQUESTTYPE_BE | (isset($_REQUEST['route']) && strpos($_REQUEST['route'], '/ajax/') === 0 ? TYPO3_REQUESTTYPE_AJAX : 0))
->baseSetup($this->entryPointLevel);

// Redirect to install tool if base configuration is not found
if (!$this->bootstrap->checkIfEssentialConfigurationExists()) {
$this->sendResponse($this->installToolRedirect());
exit;
if (!$this->checkIfEssentialConfigurationExists()) {
return $this->installToolRedirect();
}

$this->bootstrap->configure();
return parent::handle($request);
}

/**
* Define constants and variables
* Check if LocalConfiguration.php and PackageStates.php exist
*
* @return bool TRUE when the essential configuration is available, otherwise FALSE
*/
protected function defineLegacyConstants()
protected function checkIfEssentialConfigurationExists(): bool
{
define('TYPO3_MODE', 'BE');
return file_exists($this->configurationManager->getLocalConfigurationFileLocation()) && file_exists(PATH_typo3conf . 'PackageStates.php');
}

/**
Expand All @@ -85,7 +78,6 @@ protected function defineLegacyConstants()
*/
protected function installToolRedirect(): ResponseInterface
{
$path = '../' . TYPO3_mainDir . 'install.php';
return new RedirectResponse($path, 302);
return new RedirectResponse('./install.php', 302);
}
}
4 changes: 2 additions & 2 deletions typo3/sysext/backend/Resources/Private/Php/backend.php
Expand Up @@ -20,6 +20,6 @@
// Set up the application for the backend
call_user_func(function () {
$classLoader = require __DIR__ . '/../../../../../../vendor/autoload.php';

(new \TYPO3\CMS\Backend\Http\Application($classLoader))->run();
\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();
});
32 changes: 1 addition & 31 deletions typo3/sysext/core/Classes/Console/CommandApplication.php
Expand Up @@ -15,7 +15,6 @@
*/
use Symfony\Component\Console\Input\ArgvInput;
use TYPO3\CMS\Core\Core\ApplicationInterface;
use TYPO3\CMS\Core\Core\Bootstrap;
use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
Expand All @@ -26,31 +25,10 @@
class CommandApplication implements ApplicationInterface
{
/**
* @var Bootstrap
*/
protected $bootstrap;

/**
* Number of subdirectories where the entry script is located, relative to PATH_site
* @var int
*/
protected $entryPointLevel = 4;

/**
* Constructor setting up legacy constants and register available Request Handlers
*
* @param \Composer\Autoload\ClassLoader $classLoader an instance of the class loader
*/
public function __construct($classLoader)
public function __construct()
{
$this->checkEnvironmentOrDie();
$this->defineLegacyConstants();
$this->bootstrap = Bootstrap::getInstance()
->initializeClassLoader($classLoader)
->setRequestType(TYPO3_REQUESTTYPE_CLI)
->baseSetup($this->entryPointLevel);

$this->bootstrap->configure();
}

/**
Expand All @@ -68,14 +46,6 @@ public function run(callable $execute = null)
}
}

/**
* Define constants and variables
*/
protected function defineLegacyConstants()
{
define('TYPO3_MODE', 'BE');
}

/**
* Check the script is called from a cli environment.
*/
Expand Down

0 comments on commit a388232

Please sign in to comment.