From 941b8193a579bede9fd976b5e2af12dd291e860d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20M=C3=BCller?= <typo3@krue.ml> Date: Mon, 7 Nov 2022 11:00:01 +0100 Subject: [PATCH] [FEATURE] Allow global services configuration The Service Configuration for the dependency container is now also checked in `config/system/services.yaml` or `config/system/services.php`. Note that this only works in Composer-based installations where the project root is outside the document root. Resolves: #98912 Resolves: #98316 Releases: main Change-Id: Id60b3614a59a28f38aafb372389002fc13b2d3ee Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/76449 Tested-by: core-ci <typo3@b13.com> Tested-by: Susanne Moog <look@susi.dev> Tested-by: Benni Mack <benni@typo3.org> Reviewed-by: Benjamin Franzke <bfr@qbus.de> Reviewed-by: Susanne Moog <look@susi.dev> Reviewed-by: Benni Mack <benni@typo3.org> --- .../DependencyInjection/ContainerBuilder.php | 15 ++++++ ...nstallation-wide-ServicesConfiguration.rst | 54 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 typo3/sysext/core/Documentation/Changelog/12.1/Feature-98912-Installation-wide-ServicesConfiguration.rst diff --git a/typo3/sysext/core/Classes/DependencyInjection/ContainerBuilder.php b/typo3/sysext/core/Classes/DependencyInjection/ContainerBuilder.php index 352dd4557faa..f495df8cdc76 100644 --- a/typo3/sysext/core/Classes/DependencyInjection/ContainerBuilder.php +++ b/typo3/sysext/core/Classes/DependencyInjection/ContainerBuilder.php @@ -25,6 +25,7 @@ use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Cache\Frontend\PhpFrontend; +use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Package\Cache\PackageDependentCacheIdentifier; use TYPO3\CMS\Core\Package\PackageManager; @@ -117,6 +118,20 @@ class ContainerBuilder $containerBuilder->addCompilerPass(new ServiceProviderCompilationPass($registry, $this->serviceProviderRegistryServiceName)); + $globalConfigDir = Environment::getConfigPath(); + // If the config folder is outside of the document root, we allow further services per-project + // This is usually the case in composer-based installations + if (Environment::isComposerMode() && Environment::getPublicPath() !== Environment::getProjectPath()) { + if (file_exists($globalConfigDir . '/system/services.php')) { + $phpFileLoader = new PhpFileLoader($containerBuilder, new FileLocator($globalConfigDir . '/system')); + $phpFileLoader->load('services.php'); + } + if (file_exists($globalConfigDir . '/system/services.yaml')) { + $yamlFileLoader = new YamlFileLoader($containerBuilder, new FileLocator($globalConfigDir . '/system')); + $yamlFileLoader->load('services.yaml'); + } + } + $packages = $packageManager->getActivePackages(); foreach ($packages as $package) { $diConfigDir = $package->getPackagePath() . 'Configuration/'; diff --git a/typo3/sysext/core/Documentation/Changelog/12.1/Feature-98912-Installation-wide-ServicesConfiguration.rst b/typo3/sysext/core/Documentation/Changelog/12.1/Feature-98912-Installation-wide-ServicesConfiguration.rst new file mode 100644 index 000000000000..6b6eb388a08b --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/12.1/Feature-98912-Installation-wide-ServicesConfiguration.rst @@ -0,0 +1,54 @@ +.. include:: /Includes.rst.txt + +.. _feature-98912-1667814888: + +========================================================== +Feature: #98912 - Installation-wide services configuration +========================================================== + +See :issue:`98912` + +Description +=========== + +With TYPO3 v12, it is possible to set up a global services configuration for a +project that can be used in multiple project-specific extensions. This way you +can, for example, alias an interface with a concrete implementation to be used in +several extensions. It is also possible to register project-specific CLI commands +without having the need for a project-specific extension. + +However, this only works - due to security restrictions - if TYPO3 is configured +in a way that the project root is outside the document root, which usually +happens in Composer-based installations. + +Impact +====== + +The global services configuration files :file:`services.yaml` and +:file:`services.php` are now read within the the :file:`config/system/` path +of a TYPO3 project in Composer-based installations. + +Example +------- + +You want to use the interface of the PHP package `stella-maris/clock` as type +hint for DI in the service classes of your project's various extensions. Then +the concrete implementation may change without touching your code. In this +example we use `lcobucci/clock` for the concrete implementation. + +.. code-block:: php + :caption: config/system/services.php + + use Lcobucci\Clock\SystemClock; + use StellaMaris\Clock\ClockInterface; + use Symfony\Component\DependencyInjection\ContainerBuilder; + use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; + + return static function (ContainerConfigurator $containerConfigurator, ContainerBuilder $containerBuilder): void { + $services = $containerConfigurator->services(); + $services->set(ClockInterface::class) + ->factory([SystemClock::class, 'fromUTC']); + }; + + +.. index:: ext:core -- GitLab