[FrameworkBundle] WebTestCase KernelBrowser::getContainer null return type

This commit is contained in:
Amrouche Hamza 2019-04-23 08:04:30 +02:00 committed by Nicolas Grekas
parent b8294398cc
commit e169e1a4d5
9 changed files with 87 additions and 34 deletions

View File

@ -60,7 +60,7 @@ DependencyInjection
```php ```php
new Definition('%my_class%'); new Definition('%my_class%');
``` ```
DoctrineBridge DoctrineBridge
-------------- --------------
* Deprecated injecting `ClassMetadataFactory` in `DoctrineExtractor`, an instance of `EntityManagerInterface` should be * Deprecated injecting `ClassMetadataFactory` in `DoctrineExtractor`, an instance of `EntityManagerInterface` should be
@ -96,7 +96,7 @@ FrameworkBundle
* Deprecated `routing.loader.service`, use `routing.loader.container` instead. * Deprecated `routing.loader.service`, use `routing.loader.container` instead.
* Not tagging service route loaders with `routing.route_loader` has been deprecated. * Not tagging service route loaders with `routing.route_loader` has been deprecated.
* Overriding the methods `KernelTestCase::tearDown()` and `WebTestCase::tearDown()` without the `void` return-type is deprecated. * Overriding the methods `KernelTestCase::tearDown()` and `WebTestCase::tearDown()` without the `void` return-type is deprecated.
HttpClient HttpClient
---------- ----------
@ -139,7 +139,7 @@ HttpKernel
} }
``` ```
As many bundles must be compatible with a range of Symfony versions, the current As many bundles must be compatible with a range of Symfony versions, the current
directory convention is not deprecated yet, but it will be in the future. directory convention is not deprecated yet, but it will be in the future.
* Deprecated the second and third argument of `KernelInterface::locateResource` * Deprecated the second and third argument of `KernelInterface::locateResource`
@ -148,6 +148,7 @@ HttpKernel
fallback directories. Resources like service definitions are usually loaded relative to the fallback directories. Resources like service definitions are usually loaded relative to the
current directory or with a glob pattern. The fallback directories have never been advocated current directory or with a glob pattern. The fallback directories have never been advocated
so you likely do not use those in any app based on the SF Standard or Flex edition. so you likely do not use those in any app based on the SF Standard or Flex edition.
* Getting the container from a non-booted kernel is deprecated
Lock Lock
---- ----
@ -171,7 +172,7 @@ MonologBridge
-------------- --------------
* The `RouteProcessor` has been marked final. * The `RouteProcessor` has been marked final.
Process Process
------- -------
@ -195,14 +196,14 @@ Security
* Implementations of `PasswordEncoderInterface` and `UserPasswordEncoderInterface` should add a new `needsRehash()` method * Implementations of `PasswordEncoderInterface` and `UserPasswordEncoderInterface` should add a new `needsRehash()` method
* Deprecated returning a non-boolean value when implementing `Guard\AuthenticatorInterface::checkCredentials()`. Please explicitly return `false` to indicate invalid credentials. * Deprecated returning a non-boolean value when implementing `Guard\AuthenticatorInterface::checkCredentials()`. Please explicitly return `false` to indicate invalid credentials.
* Deprecated passing more than one attribute to `AccessDecisionManager::decide()` and `AuthorizationChecker::isGranted()` (and indirectly the `is_granted()` Twig and ExpressionLanguage function) * Deprecated passing more than one attribute to `AccessDecisionManager::decide()` and `AuthorizationChecker::isGranted()` (and indirectly the `is_granted()` Twig and ExpressionLanguage function)
**Before** **Before**
```php ```php
if ($this->authorizationChecker->isGranted(['ROLE_USER', 'ROLE_ADMIN'])) { if ($this->authorizationChecker->isGranted(['ROLE_USER', 'ROLE_ADMIN'])) {
// ... // ...
} }
``` ```
**After** **After**
```php ```php
if ($this->authorizationChecker->isGranted(new Expression("has_role('ROLE_USER') or has_role('ROLE_ADMIN')"))) {} if ($this->authorizationChecker->isGranted(new Expression("has_role('ROLE_USER') or has_role('ROLE_ADMIN')"))) {}
@ -230,18 +231,18 @@ TwigBridge
* Deprecated to pass `$rootDir` and `$fileLinkFormatter` as 5th and 6th argument respectively to the * Deprecated to pass `$rootDir` and `$fileLinkFormatter` as 5th and 6th argument respectively to the
`DebugCommand::__construct()` method, swap the variables position. `DebugCommand::__construct()` method, swap the variables position.
* Deprecated accepting STDIN implicitly when using the `lint:twig` command, use `lint:twig -` (append a dash) instead to make it explicit. * Deprecated accepting STDIN implicitly when using the `lint:twig` command, use `lint:twig -` (append a dash) instead to make it explicit.
TwigBundle TwigBundle
---------- ----------
* Deprecated `twig.exception_controller` configuration option, set it to "null" and use `framework.error_controller` instead: * Deprecated `twig.exception_controller` configuration option, set it to "null" and use `framework.error_controller` instead:
Before: Before:
```yaml ```yaml
twig: twig:
exception_controller: 'App\Controller\MyExceptionController' exception_controller: 'App\Controller\MyExceptionController'
``` ```
After: After:
```yaml ```yaml
twig: twig:
@ -250,36 +251,36 @@ TwigBundle
framework: framework:
error_controller: 'App\Controller\MyExceptionController' error_controller: 'App\Controller\MyExceptionController'
``` ```
The new default exception controller will also change the error response content according to The new default exception controller will also change the error response content according to
https://tools.ietf.org/html/rfc7807 for `json`, `xml`, `atom` and `txt` formats: https://tools.ietf.org/html/rfc7807 for `json`, `xml`, `atom` and `txt` formats:
Before: Before:
```json ```json
{ {
"error": { "error": {
"code": 404, "code": 404,
"message": "Sorry, the page you are looking for could not be found" "message": "Sorry, the page you are looking for could not be found"
} }
} }
``` ```
After: After:
```json ```json
{ {
"title": "Not Found", "title": "Not Found",
"status": 404, "status": 404,
"detail": "Sorry, the page you are looking for could not be found" "detail": "Sorry, the page you are looking for could not be found"
} }
``` ```
* Deprecated the `ExceptionController` and `PreviewErrorController` controllers, use `ErrorController` from the HttpKernel component instead * Deprecated the `ExceptionController` and `PreviewErrorController` controllers, use `ErrorController` from the HttpKernel component instead
* Deprecated all built-in error templates, use the error renderer mechanism of the `ErrorRenderer` component * Deprecated all built-in error templates, use the error renderer mechanism of the `ErrorRenderer` component
* Deprecated loading custom error templates in non-html formats. Custom HTML error pages based on Twig keep working as before: * Deprecated loading custom error templates in non-html formats. Custom HTML error pages based on Twig keep working as before:
Before (`templates/bundles/TwigBundle/Exception/error.jsonld.twig`): Before (`templates/bundles/TwigBundle/Exception/error.jsonld.twig`):
```twig ```twig
{ {
"@id": "https://example.com", "@id": "https://example.com",
"@type": "error", "@type": "error",
"@context": { "@context": {
@ -289,7 +290,7 @@ TwigBundle
} }
} }
``` ```
After (`App\ErrorRenderer\JsonLdErrorRenderer`): After (`App\ErrorRenderer\JsonLdErrorRenderer`):
```php ```php
class JsonLdErrorRenderer implements ErrorRendererInterface class JsonLdErrorRenderer implements ErrorRendererInterface
@ -298,7 +299,7 @@ TwigBundle
{ {
return 'jsonld'; return 'jsonld';
} }
public function render(FlattenException $exception): string public function render(FlattenException $exception): string
{ {
return json_encode([ return json_encode([
@ -323,7 +324,7 @@ Validator
* Deprecated using anything else than a `string` as the code of a `ConstraintViolation`, a `string` type-hint will * Deprecated using anything else than a `string` as the code of a `ConstraintViolation`, a `string` type-hint will
be added to the constructor of the `ConstraintViolation` class and to the `ConstraintViolationBuilder::setCode()` be added to the constructor of the `ConstraintViolation` class and to the `ConstraintViolationBuilder::setCode()`
method in 5.0. method in 5.0.
* Deprecated passing an `ExpressionLanguage` instance as the second argument of `ExpressionValidator::__construct()`. * Deprecated passing an `ExpressionLanguage` instance as the second argument of `ExpressionValidator::__construct()`.
Pass it as the first argument instead. Pass it as the first argument instead.
* The `Length` constraint expects the `allowEmptyString` option to be defined * The `Length` constraint expects the `allowEmptyString` option to be defined
when the `min` option is used. when the `min` option is used.
@ -343,7 +344,7 @@ WebServerBundle
--------------- ---------------
* The bundle is deprecated and will be removed in 5.0. * The bundle is deprecated and will be removed in 5.0.
Yaml Yaml
---- ----

View File

@ -288,6 +288,7 @@ HttpFoundation
use `Symfony\Component\Mime\FileinfoMimeTypeGuesser` instead. use `Symfony\Component\Mime\FileinfoMimeTypeGuesser` instead.
* `ApacheRequest` has been removed, use the `Request` class instead. * `ApacheRequest` has been removed, use the `Request` class instead.
* The third argument of the `HeaderBag::get()` method has been removed, use method `all()` instead. * The third argument of the `HeaderBag::get()` method has been removed, use method `all()` instead.
* Getting the container from a non-booted kernel is not possible anymore.
HttpKernel HttpKernel
---------- ----------

View File

@ -127,11 +127,15 @@ abstract class KernelTestCase extends TestCase
protected static function ensureKernelShutdown() protected static function ensureKernelShutdown()
{ {
if (null !== static::$kernel) { if (null !== static::$kernel) {
$container = static::$kernel->getContainer(); $isBooted = (new \ReflectionClass(static::$kernel))->getProperty('booted');
static::$kernel->shutdown(); $isBooted->setAccessible(true);
static::$booted = false; if ($isBooted->getValue(static::$kernel)) {
if ($container instanceof ResetInterface) { $container = static::$kernel->getContainer();
$container->reset(); static::$kernel->shutdown();
static::$booted = false;
if ($container instanceof ResetInterface) {
$container->reset();
}
} }
} }
static::$container = null; static::$container = null;

View File

@ -14,6 +14,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\app;
use Psr\Log\NullLogger; use Psr\Log\NullLogger;
use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\Kernel;
@ -96,4 +97,13 @@ class AppKernel extends Kernel
return $parameters; return $parameters;
} }
public function getContainer(): ContainerInterface
{
if (!$this->booted) {
throw new \LogicException('Cannot access the container on a non-booted kernel. Did you forget to boot it?');
}
return parent::getContainer();
}
} }

View File

@ -12,6 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\Tests\Functional\app; namespace Symfony\Bundle\SecurityBundle\Tests\Functional\app;
use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\Kernel;
@ -98,4 +99,13 @@ class AppKernel extends Kernel
return $parameters; return $parameters;
} }
public function getContainer(): ContainerInterface
{
if (!$this->booted) {
throw new \LogicException('Cannot access the container on a non-booted kernel. Did you forget to boot it?');
}
return parent::getContainer();
}
} }

View File

@ -14,6 +14,7 @@ CHANGELOG
so you likely do not use those in any app based on the SF Standard or Flex edition. so you likely do not use those in any app based on the SF Standard or Flex edition.
* Marked all dispatched event classes as `@final` * Marked all dispatched event classes as `@final`
* Added `ErrorController` to enable the preview and error rendering mechanism * Added `ErrorController` to enable the preview and error rendering mechanism
* Getting the container from a non-booted kernel is deprecated.
4.3.0 4.3.0
----- -----

View File

@ -380,6 +380,10 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
*/ */
public function getContainer() public function getContainer()
{ {
if (!$this->booted) {
@trigger_error('Getting the container from a non-booted kernel is deprecated since Symfony 4.4.', E_USER_DEPRECATED);
}
return $this->container; return $this->container;
} }

View File

@ -124,7 +124,7 @@ interface KernelInterface extends HttpKernelInterface
/** /**
* Gets the current container. * Gets the current container.
* *
* @return ContainerInterface|null A ContainerInterface instance or null when the Kernel is shutdown * @return ContainerInterface
*/ */
public function getContainer(); public function getContainer();

View File

@ -46,6 +46,17 @@ class KernelTest extends TestCase
$this->assertEquals($debug, $kernel->isDebug()); $this->assertEquals($debug, $kernel->isDebug());
$this->assertFalse($kernel->isBooted()); $this->assertFalse($kernel->isBooted());
$this->assertLessThanOrEqual(microtime(true), $kernel->getStartTime()); $this->assertLessThanOrEqual(microtime(true), $kernel->getStartTime());
}
/**
* @group legacy
* @expectedDeprecation Getting the container from a non-booted kernel is deprecated since Symfony 4.4.
*/
public function testGetContainerForANonBootedKernel()
{
$kernel = new KernelForTest('test_env', true);
$this->assertFalse($kernel->isBooted());
$this->assertNull($kernel->getContainer()); $this->assertNull($kernel->getContainer());
} }
@ -61,7 +72,6 @@ class KernelTest extends TestCase
$this->assertEquals($debug, $clone->isDebug()); $this->assertEquals($debug, $clone->isDebug());
$this->assertFalse($clone->isBooted()); $this->assertFalse($clone->isBooted());
$this->assertLessThanOrEqual(microtime(true), $clone->getStartTime()); $this->assertLessThanOrEqual(microtime(true), $clone->getStartTime());
$this->assertNull($clone->getContainer());
} }
public function testClassNameValidityGetter() public function testClassNameValidityGetter()
@ -486,6 +496,18 @@ EOF;
$kernel->terminate(Request::create('/'), new Response()); $kernel->terminate(Request::create('/'), new Response());
} }
/**
* @group legacy
* @expectedDeprecation Getting the container from a non-booted kernel is deprecated since Symfony 4.4.
*/
public function testDeprecatedNullKernel()
{
$kernel = $this->getKernel();
$kernel->shutdown();
$this->assertNull($kernel->getContainer());
}
public function testTerminateDelegatesTerminationOnlyForTerminableInterface() public function testTerminateDelegatesTerminationOnlyForTerminableInterface()
{ {
// does not implement TerminableInterface // does not implement TerminableInterface