From 09c653011518147ed906ea297504cceb529a1d17 Mon Sep 17 00:00:00 2001 From: Adrian Zmenda Date: Sun, 18 Mar 2018 16:59:11 +0100 Subject: [PATCH 1/5] Add autoconfiguration for Symfony 4, allow overriding .env setting by using explicit env and debug settings, tweaks --- features/not_crashing_behat.feature | 79 ++++++++++++++-- src/ServiceContainer/SymfonyExtension.php | 104 +++++++++++++++++----- 2 files changed, 151 insertions(+), 32 deletions(-) diff --git a/features/not_crashing_behat.feature b/features/not_crashing_behat.feature index fbad0c3..69f0135 100644 --- a/features/not_crashing_behat.feature +++ b/features/not_crashing_behat.feature @@ -3,7 +3,7 @@ Feature: Not crashing Behat As a Behat User I want to have Behat up and running after enabling this extension - Scenario: Not crashing Behat + Scenario: Successful boot the Symfony kernel with autoconfiguration Given a Behat configuration containing: """ default: @@ -29,7 +29,7 @@ Feature: Not crashing Behat When I run Behat Then it should pass - Scenario: Not crashing Behat with CrossContainerExtension + Scenario: Successful boot the Symfony kernel with explicit configuration Given a Behat configuration containing: """ default: @@ -37,17 +37,19 @@ Feature: Not crashing Behat FriendsOfBehat\SymfonyExtension: kernel: bootstrap: ~ - - FriendsOfBehat\CrossContainerExtension: ~ + path: app/MyKernel.php + class: MyKernel + env: test + debug: true """ - And a file "app/AppKernel.php" containing: + And a file "app/MyKernel.php" containing: """ null, + 'kernel' => [ + 'bootstrap' => 'app/autoload.php', + 'path' => 'app/AppKernel.php', + 'class' => 'AppKernel', + 'env' => self::DEFAULT_ENV, + 'debug' => self::DEFAULT_DEBUG_MODE + ] + ]; + + /** + * Default Symfony 4 configuration + */ + private const SYMFONY_4_DEFAULTS = [ + 'env_file' => '.env', + 'kernel' => [ + 'bootstrap' => null, + 'path' => 'src/Kernel.php', + 'class' => 'App\Kernel', + 'env' => self::DEFAULT_ENV, + 'debug' => self::DEFAULT_DEBUG_MODE + ] + ]; /** * @var CrossContainerProcessor|null @@ -91,18 +119,15 @@ final class SymfonyExtension implements Extension public function configure(ArrayNodeDefinition $builder): void { $builder - ->addDefaultsIfNotSet() - ->children() - ->scalarNode('env_file')->defaultNull()->end() - ->arrayNode('kernel') - ->addDefaultsIfNotSet() - ->children() - ->scalarNode('bootstrap')->defaultValue('app/autoload.php')->end() - ->scalarNode('path')->defaultValue('app/AppKernel.php')->end() - ->scalarNode('class')->defaultValue('AppKernel')->end() - ->scalarNode('env')->defaultValue('test')->end() - ->booleanNode('debug')->defaultTrue()->end() - ->end() + ->children() + ->scalarNode('env_file')->end() + ->arrayNode('kernel') + ->children() + ->scalarNode('bootstrap')->end() + ->scalarNode('path')->end() + ->scalarNode('class')->end() + ->scalarNode('env')->end() + ->booleanNode('debug')->end() ->end() ->end() ->end() @@ -114,17 +139,7 @@ final class SymfonyExtension implements Extension */ public function load(ContainerBuilder $container, array $config): void { - if (null !== $config['env_file']) { - $envFilePath = sprintf('%s/%s', $container->getParameter('paths.base'), $config['env_file']); - $envFilePath = file_exists($envFilePath) ? $envFilePath : $envFilePath.'.dist'; - (new Dotenv())->load($envFilePath); - - $environment = false !== getenv('APP_ENV') ? getenv('APP_ENV') : self::DEFAULT_ENV; - $debugMode = false !== getenv('APP_DEBUG') ? getenv('APP_DEBUG') : self::DEBUG_MODE; - - $config['kernel']['env'] = $environment; - $config['kernel']['kernel'] = $debugMode; - } + $config = $this->autoconfigure($container, $config); $this->loadKernel($container, $config['kernel']); $this->loadKernelContainer($container); @@ -145,6 +160,47 @@ final class SymfonyExtension implements Extension { } + /** + * @param ContainerBuilder $container + * @param array $userConfig + * @return array + */ + private function autoconfigure(ContainerBuilder $container, array $userConfig) { + + $defaults = self::SYMFONY_DEFAULTS; + + $symfonyFlexKernelPath = sprintf('%s/%s', $container->getParameter('paths.base'), self::SYMFONY_4_DEFAULTS['kernel']['path']); + if (file_exists($symfonyFlexKernelPath)) { + $defaults = self::SYMFONY_4_DEFAULTS; + } + + $config = array_replace_recursive($defaults, $userConfig); + + if (null !== $config['env_file']) { + $this->loadEnvVars($container, $config['env_file']); + + if (!isset($userConfig['kernel']['env']) && false !== getenv('APP_ENV')) { + $config['kernel']['env'] = getenv('APP_ENV'); + } + + if (!isset($userConfig['kernel']['debug']) && false !== getenv('APP_DEBUG')) { + $config['kernel']['debug'] = getenv('APP_DEBUG'); + } + } + + return $config; + } + + /** + * @param ContainerBuilder $container + * @param string $fileName + */ + private function loadEnvVars(ContainerBuilder $container, string $fileName): void + { + $envFilePath = sprintf('%s/%s', $container->getParameter('paths.base'), $fileName); + (new Dotenv())->load($envFilePath); + } + /** * @param ContainerBuilder $container */ From 141074a24e7aa198d4b6095572a78226f89a5d33 Mon Sep 17 00:00:00 2001 From: Adrian Zmenda Date: Sun, 18 Mar 2018 17:27:11 +0100 Subject: [PATCH 2/5] Tweak README to include new configuration details for Symfony 4, tweak variable name --- README.md | 62 +++++++++++++---------- src/ServiceContainer/SymfonyExtension.php | 4 +- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 631faed..18b8f35 100644 --- a/README.md +++ b/README.md @@ -28,30 +28,40 @@ ensures that application behaviour will not be affected by stateful services. FriendsOfBehat\SymfonyExtension: ~ ``` - **Symfony 3 configuration** - - ``` - FriendsOfBehat\SymfonyExtension: - kernel: - bootstrap: 'var/bootstrap.php.cache' - path: app/AppKernel.php - class: 'AppKernel' - env: test - debug: true - ``` - - **Symfony 4 configuration** - - ``` - FriendsOfBehat\SymfonyExtension: - # .env.dist file will be used if .env file does not exist - env_file: .env - kernel: - class: 'MyTrip\Kernel' - path: src/Kernel.php - debug: true - ``` - - Symfony 4 does not have bootstrap file anymore and the environment is configured in the .env file. - 3. Good luck & have fun! + + +## Configuration + +SymfonyExtension provides kind of autoconfiguration feature. +When none explicit configuration is set, we will set for You sane default that will get you running fast. + +**Default Symfony 3 configuration** + +``` +FriendsOfBehat\SymfonyExtension: + kernel: + bootstrap: 'app/autoload.php' # you may want to use var/bootstrap.php.cache instead + path: app/AppKernel.php + class: 'AppKernel' + env: test + debug: true +``` + +**Default Symfony 4 configuration** + +``` +FriendsOfBehat\SymfonyExtension: + # .env.dist file will be used if .env file does not exist + env_file: .env + kernel: + bootstrap: ~ + path: src/Kernel.php + class: 'App\Kernel' + env: test # When explicitly set, will override APP_ENV loaded from env_file file + debug: true # When explicitly set, will override APP_DEBUG loaded from env_file file +``` + +Symfony 4 is detected, based on the existence of `src/Kernel.php` file, so if you did not migrate to new Symfony structure yet; you need to set those values yourself. + +Of course, you can always change each of those settings. diff --git a/src/ServiceContainer/SymfonyExtension.php b/src/ServiceContainer/SymfonyExtension.php index bceb678..87ee0f7 100644 --- a/src/ServiceContainer/SymfonyExtension.php +++ b/src/ServiceContainer/SymfonyExtension.php @@ -169,8 +169,8 @@ final class SymfonyExtension implements Extension $defaults = self::SYMFONY_DEFAULTS; - $symfonyFlexKernelPath = sprintf('%s/%s', $container->getParameter('paths.base'), self::SYMFONY_4_DEFAULTS['kernel']['path']); - if (file_exists($symfonyFlexKernelPath)) { + $symfony4KernelPath = sprintf('%s/%s', $container->getParameter('paths.base'), self::SYMFONY_4_DEFAULTS['kernel']['path']); + if (file_exists($symfony4KernelPath)) { $defaults = self::SYMFONY_4_DEFAULTS; } From 149d41087ff3d1848e9fe3c47f54a0c71a1d8744 Mon Sep 17 00:00:00 2001 From: Adrian Zmenda Date: Fri, 10 Aug 2018 17:56:50 +0200 Subject: [PATCH 3/5] Add symfony 4 configuration loading when bootstrap is null; tweaked formatting, naming, tests and readme --- README.md | 15 ++++++++++++- features/not_crashing_behat.feature | 26 ++++++++++++++++------- src/ServiceContainer/SymfonyExtension.php | 13 +++++++----- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 18b8f35..ed97e39 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,19 @@ FriendsOfBehat\SymfonyExtension: debug: true # When explicitly set, will override APP_DEBUG loaded from env_file file ``` -Symfony 4 is detected, based on the existence of `src/Kernel.php` file, so if you did not migrate to new Symfony structure yet; you need to set those values yourself. +Symfony 4 is automatically detected, based on the existence of default `src/Kernel.php` kernel file. + +If you did not migrate to new Symfony structure yet or you are using custom paths/naming; you need to configure `kernel.boostrap` parameter, to enable default Symfony 4 configuration as shown in the example below: + +``` +FriendsOfBehat\SymfonyExtension: + # env_file: .env # loaded from the default configuration + kernel: + bootstrap: ~ # this enables default Symfony 4 configuration + path: app/AppKernel.php + # class: 'App\Kernel' # loaded from the default configuration + # env: test # loaded from the default configuration + # debug: true # loaded from the default configuration +``` Of course, you can always change each of those settings. diff --git a/features/not_crashing_behat.feature b/features/not_crashing_behat.feature index 69f0135..a2e0f7b 100644 --- a/features/not_crashing_behat.feature +++ b/features/not_crashing_behat.feature @@ -8,9 +8,12 @@ Feature: Not crashing Behat """ default: extensions: - FriendsOfBehat\SymfonyExtension: - kernel: - bootstrap: ~ + FriendsOfBehat\SymfonyExtension: ~ + """ + And a file "app/autoload.php" containing: + """ + children() ->scalarNode('env_file')->end() ->arrayNode('kernel') + ->addDefaultsIfNotSet() ->children() - ->scalarNode('bootstrap')->end() + ->scalarNode('bootstrap')->defaultFalse()->end() ->scalarNode('path')->end() ->scalarNode('class')->end() ->scalarNode('env')->end() @@ -165,15 +166,17 @@ final class SymfonyExtension implements Extension * @param array $userConfig * @return array */ - private function autoconfigure(ContainerBuilder $container, array $userConfig) { - + private function autoconfigure(ContainerBuilder $container, array $userConfig): array + { $defaults = self::SYMFONY_DEFAULTS; - $symfony4KernelPath = sprintf('%s/%s', $container->getParameter('paths.base'), self::SYMFONY_4_DEFAULTS['kernel']['path']); - if (file_exists($symfony4KernelPath)) { + $symfonyFourKernelPath = sprintf('%s/%s', $container->getParameter('paths.base'), self::SYMFONY_4_DEFAULTS['kernel']['path']); + if ($userConfig['kernel']['bootstrap'] === null || file_exists($symfonyFourKernelPath)) { $defaults = self::SYMFONY_4_DEFAULTS; } + $userConfig['kernel']['bootstrap'] = $userConfig['kernel']['bootstrap'] === false ? null : $userConfig['kernel']['bootstrap']; + $config = array_replace_recursive($defaults, $userConfig); if (null !== $config['env_file']) { From 49c4fc2a0e7c2707047337caf883d66e1bef110b Mon Sep 17 00:00:00 2001 From: Adrian Zmenda Date: Fri, 10 Aug 2018 18:54:32 +0200 Subject: [PATCH 4/5] Tweak README typos --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ed97e39..b89f9f1 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ ensures that application behaviour will not be affected by stateful services. ## Configuration SymfonyExtension provides kind of autoconfiguration feature. -When none explicit configuration is set, we will set for You sane default that will get you running fast. +When none explicit configuration is set, we will set for you sane default that will get you running fast. **Default Symfony 3 configuration** @@ -64,7 +64,7 @@ FriendsOfBehat\SymfonyExtension: Symfony 4 is automatically detected, based on the existence of default `src/Kernel.php` kernel file. -If you did not migrate to new Symfony structure yet or you are using custom paths/naming; you need to configure `kernel.boostrap` parameter, to enable default Symfony 4 configuration as shown in the example below: +If you did not migrate to new Symfony structure yet or you are using custom paths/naming; you need to configure `kernel.bootstrap` parameter, to enable default Symfony 4 configuration as shown in the example below: ``` FriendsOfBehat\SymfonyExtension: From 99db8631755cf7d1a5e36b8f32bfc2ee1bb0c897 Mon Sep 17 00:00:00 2001 From: Adrian Zmenda Date: Sun, 9 Dec 2018 16:11:00 +0100 Subject: [PATCH 5/5] Tweaks after CR: remove obsolete docblocks, fix code formatting to match ECS --- src/ServiceContainer/SymfonyExtension.php | 52 +++-------------------- 1 file changed, 5 insertions(+), 47 deletions(-) diff --git a/src/ServiceContainer/SymfonyExtension.php b/src/ServiceContainer/SymfonyExtension.php index 91230ad..bda7c3d 100644 --- a/src/ServiceContainer/SymfonyExtension.php +++ b/src/ServiceContainer/SymfonyExtension.php @@ -73,8 +73,8 @@ final class SymfonyExtension implements Extension 'path' => 'app/AppKernel.php', 'class' => 'AppKernel', 'env' => self::DEFAULT_ENV, - 'debug' => self::DEFAULT_DEBUG_MODE - ] + 'debug' => self::DEFAULT_DEBUG_MODE, + ], ]; /** @@ -87,8 +87,8 @@ final class SymfonyExtension implements Extension 'path' => 'src/Kernel.php', 'class' => 'App\Kernel', 'env' => self::DEFAULT_ENV, - 'debug' => self::DEFAULT_DEBUG_MODE - ] + 'debug' => self::DEFAULT_DEBUG_MODE, + ], ]; /** @@ -161,11 +161,6 @@ final class SymfonyExtension implements Extension { } - /** - * @param ContainerBuilder $container - * @param array $userConfig - * @return array - */ private function autoconfigure(ContainerBuilder $container, array $userConfig): array { $defaults = self::SYMFONY_DEFAULTS; @@ -194,19 +189,13 @@ final class SymfonyExtension implements Extension return $config; } - /** - * @param ContainerBuilder $container - * @param string $fileName - */ private function loadEnvVars(ContainerBuilder $container, string $fileName): void { $envFilePath = sprintf('%s/%s', $container->getParameter('paths.base'), $fileName); + $envFilePath = file_exists($envFilePath) ? $envFilePath : $envFilePath . '.dist'; (new Dotenv())->load($envFilePath); } - /** - * @param ContainerBuilder $container - */ private function loadKernel(ContainerBuilder $container, array $config): void { $definition = new Definition($config['class'], [ @@ -226,9 +215,6 @@ final class SymfonyExtension implements Extension $this->requireKernelBootstrapFile($container->getParameter('paths.base'), $config['bootstrap']); } - /** - * @param ContainerBuilder $container - */ private function loadKernelContainer(ContainerBuilder $container): void { $containerDefinition = new Definition(Container::class); @@ -240,25 +226,16 @@ final class SymfonyExtension implements Extension $container->setDefinition(self::KERNEL_CONTAINER_ID, $containerDefinition); } - /** - * @param ContainerBuilder $container - */ private function loadDriverKernel(ContainerBuilder $container): void { $container->setDefinition(self::DRIVER_KERNEL_ID, $container->findDefinition(self::KERNEL_ID)); } - /** - * @param ContainerBuilder $container - */ private function loadSharedKernel(ContainerBuilder $container): void { $container->setDefinition(self::SHARED_KERNEL_ID, $container->findDefinition(self::KERNEL_ID)); } - /** - * @param ContainerBuilder $container - */ private function loadSharedKernelContainer(ContainerBuilder $container): void { $containerDefinition = new Definition(Container::class); @@ -271,8 +248,6 @@ final class SymfonyExtension implements Extension } /** - * @param ContainerBuilder $container - * * @throws \Exception */ private function loadKernelRebooter(ContainerBuilder $container): void @@ -284,8 +259,6 @@ final class SymfonyExtension implements Extension } /** - * @param ContainerBuilder $container - * * @throws \Exception */ private function declareSymfonyContainers(ContainerBuilder $container): void @@ -316,9 +289,6 @@ final class SymfonyExtension implements Extension } } - /** - * @param ExtensionManager $extensionManager - */ private function initializeCrossContainerProcessor(ExtensionManager $extensionManager): void { /** @var CrossContainerExtension $extension */ @@ -328,9 +298,6 @@ final class SymfonyExtension implements Extension } } - /** - * @param ExtensionManager $extensionManager - */ private function registerSymfonyDriverFactory(ExtensionManager $extensionManager): void { /** @var MinkExtension|null $minkExtension */ @@ -345,12 +312,6 @@ final class SymfonyExtension implements Extension )); } - /** - * @param string $basePath - * @param string $kernelPath - * - * @return string|null - */ private function getKernelFile(string $basePath, string $kernelPath): ?string { $possibleFiles = [ @@ -368,9 +329,6 @@ final class SymfonyExtension implements Extension } /** - * @param string $basePath - * @param string|null $bootstrapPath - * * @throws \DomainException */ private function requireKernelBootstrapFile(string $basePath, ?string $bootstrapPath): void