Skip to content

Commit

Permalink
Merge branch '4.4' into 5.4
Browse files Browse the repository at this point in the history
* 4.4:
  fix bad help message in cache warmup command
  Fix RequestStack state if throwable is thrown
  [Serializer] Fix caching context-aware encoders/decoders in ChainEncoder/ChainDecoder
  • Loading branch information
fabpot committed Aug 26, 2022
2 parents c2c522a + e10e5bf commit c66e667
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,6 @@ protected function configure()
Before running this command, the cache must be empty.
This command does not generate the classes cache (as when executing this
command, too many classes that should be part of the cache are already loaded
in memory). Use <comment>curl</comment> or any other similar tool to warm up
the classes cache if you want.
EOF
)
;
Expand Down
6 changes: 3 additions & 3 deletions src/Symfony/Component/HttpKernel/HttpKernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public function handle(Request $request, int $type = HttpKernelInterface::MAIN_R
{
$request->headers->set('X-Php-Ob-Level', (string) ob_get_level());

$this->requestStack->push($request);
try {
return $this->handleRaw($request, $type);
} catch (\Exception $e) {
Expand All @@ -83,6 +84,8 @@ public function handle(Request $request, int $type = HttpKernelInterface::MAIN_R
}

return $this->handleThrowable($e, $request, $type);
} finally {
$this->requestStack->pop();
}
}

Expand Down Expand Up @@ -121,8 +124,6 @@ public function terminateWithException(\Throwable $exception, Request $request =
*/
private function handleRaw(Request $request, int $type = self::MAIN_REQUEST): Response
{
$this->requestStack->push($request);

// request
$event = new RequestEvent($this, $request, $type);
$this->dispatcher->dispatch($event, KernelEvents::REQUEST);
Expand Down Expand Up @@ -199,7 +200,6 @@ private function filterResponse(Response $response, Request $request, int $type)
private function finishRequest(Request $request, int $type)
{
$this->dispatcher->dispatch(new FinishRequestEvent($this, $request, $type), KernelEvents::FINISH_REQUEST);
$this->requestStack->pop();
}

/**
Expand Down
39 changes: 39 additions & 0 deletions src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,45 @@ public function testHandleWhenControllerThrowsAnExceptionAndCatchIsTrue()
$kernel->handle(new Request(), HttpKernelInterface::MAIN_REQUEST, true);
}

public function testRequestStackIsNotBrokenWhenControllerThrowsAnExceptionAndCatchIsTrue()
{
$requestStack = new RequestStack();
$kernel = $this->getHttpKernel(new EventDispatcher(), function () { throw new \RuntimeException(); }, $requestStack);

try {
$kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
} catch (\Throwable $exception) {
}

self::assertNull($requestStack->getCurrentRequest());
}

public function testRequestStackIsNotBrokenWhenControllerThrowsAnExceptionAndCatchIsFalse()
{
$requestStack = new RequestStack();
$kernel = $this->getHttpKernel(new EventDispatcher(), function () { throw new \RuntimeException(); }, $requestStack);

try {
$kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, false);
} catch (\Throwable $exception) {
}

self::assertNull($requestStack->getCurrentRequest());
}

public function testRequestStackIsNotBrokenWhenControllerThrowsAnThrowable()
{
$requestStack = new RequestStack();
$kernel = $this->getHttpKernel(new EventDispatcher(), function () { throw new \Error(); }, $requestStack);

try {
$kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
} catch (\Throwable $exception) {
}

self::assertNull($requestStack->getCurrentRequest());
}

public function testHandleWhenControllerThrowsAnExceptionAndCatchIsFalseAndNoListenerIsRegistered()
{
$this->expectException(\RuntimeException::class);
Expand Down
6 changes: 5 additions & 1 deletion src/Symfony/Component/Serializer/Encoder/ChainDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,13 @@ private function getDecoder(string $format, array $context): DecoderInterface
return $this->decoders[$this->decoderByFormat[$format]];
}

$cache = true;
foreach ($this->decoders as $i => $decoder) {
$cache = $cache && !$decoder instanceof ContextAwareDecoderInterface;
if ($decoder->supportsDecoding($format, $context)) {
$this->decoderByFormat[$format] = $i;
if ($cache) {
$this->decoderByFormat[$format] = $i;
}

return $decoder;
}
Expand Down
6 changes: 5 additions & 1 deletion src/Symfony/Component/Serializer/Encoder/ChainEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,13 @@ private function getEncoder(string $format, array $context): EncoderInterface
return $this->encoders[$this->encoderByFormat[$format]];
}

$cache = true;
foreach ($this->encoders as $i => $encoder) {
$cache = $cache && !$encoder instanceof ContextAwareEncoderInterface;
if ($encoder->supportsEncoding($format, $context)) {
$this->encoderByFormat[$format] = $i;
if ($cache) {
$this->encoderByFormat[$format] = $i;
}

return $encoder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Encoder\ChainDecoder;
use Symfony\Component\Serializer\Encoder\ContextAwareDecoderInterface;
use Symfony\Component\Serializer\Encoder\DecoderInterface;
use Symfony\Component\Serializer\Exception\RuntimeException;

Expand All @@ -28,14 +29,15 @@ class ChainDecoderTest extends TestCase

protected function setUp(): void
{
$this->decoder1 = $this->createMock(DecoderInterface::class);
$this->decoder1 = $this->createMock(ContextAwareDecoderInterface::class);
$this->decoder1
->method('supportsDecoding')
->willReturnMap([
[self::FORMAT_1, [], true],
[self::FORMAT_2, [], false],
[self::FORMAT_3, [], false],
[self::FORMAT_3, ['foo' => 'bar'], true],
[self::FORMAT_3, ['foo' => 'bar2'], false],
]);

$this->decoder2 = $this->createMock(DecoderInterface::class);
Expand All @@ -45,17 +47,35 @@ protected function setUp(): void
[self::FORMAT_1, [], false],
[self::FORMAT_2, [], true],
[self::FORMAT_3, [], false],
[self::FORMAT_3, ['foo' => 'bar'], false],
[self::FORMAT_3, ['foo' => 'bar2'], true],
]);

$this->chainDecoder = new ChainDecoder([$this->decoder1, $this->decoder2]);
}

public function testSupportsDecoding()
{
$this->decoder1
->method('decode')
->willReturn('result1');
$this->decoder2
->method('decode')
->willReturn('result2');

$this->assertTrue($this->chainDecoder->supportsDecoding(self::FORMAT_1));
$this->assertEquals('result1', $this->chainDecoder->decode('', self::FORMAT_1, []));

$this->assertTrue($this->chainDecoder->supportsDecoding(self::FORMAT_2));
$this->assertEquals('result2', $this->chainDecoder->decode('', self::FORMAT_2, []));

$this->assertFalse($this->chainDecoder->supportsDecoding(self::FORMAT_3));

$this->assertTrue($this->chainDecoder->supportsDecoding(self::FORMAT_3, ['foo' => 'bar']));
$this->assertEquals('result1', $this->chainDecoder->decode('', self::FORMAT_3, ['foo' => 'bar']));

$this->assertTrue($this->chainDecoder->supportsDecoding(self::FORMAT_3, ['foo' => 'bar2']));
$this->assertEquals('result2', $this->chainDecoder->decode('', self::FORMAT_3, ['foo' => 'bar2']));
}

public function testDecode()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Encoder\ChainEncoder;
use Symfony\Component\Serializer\Encoder\ContextAwareEncoderInterface;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
use Symfony\Component\Serializer\Encoder\NormalizationAwareInterface;
use Symfony\Component\Serializer\Exception\RuntimeException;
Expand All @@ -29,14 +30,15 @@ class ChainEncoderTest extends TestCase

protected function setUp(): void
{
$this->encoder1 = $this->createMock(EncoderInterface::class);
$this->encoder1 = $this->createMock(ContextAwareEncoderInterface::class);
$this->encoder1
->method('supportsEncoding')
->willReturnMap([
[self::FORMAT_1, [], true],
[self::FORMAT_2, [], false],
[self::FORMAT_3, [], false],
[self::FORMAT_3, ['foo' => 'bar'], true],
[self::FORMAT_3, ['foo' => 'bar2'], false],
]);

$this->encoder2 = $this->createMock(EncoderInterface::class);
Expand All @@ -46,17 +48,35 @@ protected function setUp(): void
[self::FORMAT_1, [], false],
[self::FORMAT_2, [], true],
[self::FORMAT_3, [], false],
[self::FORMAT_3, ['foo' => 'bar'], false],
[self::FORMAT_3, ['foo' => 'bar2'], true],
]);

$this->chainEncoder = new ChainEncoder([$this->encoder1, $this->encoder2]);
}

public function testSupportsEncoding()
{
$this->encoder1
->method('encode')
->willReturn('result1');
$this->encoder2
->method('encode')
->willReturn('result2');

$this->assertTrue($this->chainEncoder->supportsEncoding(self::FORMAT_1));
$this->assertEquals('result1', $this->chainEncoder->encode('', self::FORMAT_1, []));

$this->assertTrue($this->chainEncoder->supportsEncoding(self::FORMAT_2));
$this->assertEquals('result2', $this->chainEncoder->encode('', self::FORMAT_2, []));

$this->assertFalse($this->chainEncoder->supportsEncoding(self::FORMAT_3));

$this->assertTrue($this->chainEncoder->supportsEncoding(self::FORMAT_3, ['foo' => 'bar']));
$this->assertEquals('result1', $this->chainEncoder->encode('', self::FORMAT_3, ['foo' => 'bar']));

$this->assertTrue($this->chainEncoder->supportsEncoding(self::FORMAT_3, ['foo' => 'bar2']));
$this->assertEquals('result2', $this->chainEncoder->encode('', self::FORMAT_3, ['foo' => 'bar2']));
}

public function testEncode()
Expand Down

0 comments on commit c66e667

Please sign in to comment.