Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
namespace FOS\RestBundle\DependencyInjection\Compiler;

use FOS\RestBundle\Serializer\JMSHandlerRegistry;
use FOS\RestBundle\Serializer\JMSHandlerRegistryV2;
use JMS\Serializer\Visitor\SerializationVisitorInterface;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
Expand All @@ -38,7 +40,7 @@ public function process(ContainerBuilder $container)
$jmsHandlerRegistry->setPublic(false);
$container->setDefinition('fos_rest.serializer.jms_handler_registry.inner', $jmsHandlerRegistry);

$fosRestHandlerRegistry = $container->register('jms_serializer.handler_registry', JMSHandlerRegistry::class)
$fosRestHandlerRegistry = $container->register('jms_serializer.handler_registry', interface_exists(SerializationVisitorInterface::class) ? JMSHandlerRegistryV2::class : JMSHandlerRegistry::class)
->setPublic($public)
->addArgument(new Reference('fos_rest.serializer.jms_handler_registry.inner'));

Expand Down
61 changes: 61 additions & 0 deletions Serializer/JMSHandlerRegistryV2.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

/*
* This file is part of the FOSRestBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FOS\RestBundle\Serializer;

use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\Handler\HandlerRegistryInterface;

/**
* Search in the class parents to find an adapted handler.
*
* @author Ener-Getick <[email protected]>
*
* @internal do not depend on this class directly
*/
final class JMSHandlerRegistryV2 implements HandlerRegistryInterface
{
private $registry;

public function __construct(HandlerRegistryInterface $registry)
{
$this->registry = $registry;
}

/**
* {@inheritdoc}
*/
public function registerSubscribingHandler(SubscribingHandlerInterface $handler): void
{
$this->registry->registerSubscribingHandler($handler);
}

/**
* {@inheritdoc}
*/
public function registerHandler(int $direction, string $typeName, string $format, $handler): void
{
$this->registry->registerHandler($direction, $typeName, $format, $handler);
}

/**
* {@inheritdoc}
*/
public function getHandler(int $direction, string $typeName, string $format)
{
do {
$handler = $this->registry->getHandler($direction, $typeName, $format);
if (null !== $handler) {
return $handler;
}
} while ($typeName = get_parent_class($typeName));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this was used for the exception handler, will it make sense to limit this behavior only for classes extending Exception ?

Performance of this loop are really impacting serialization performance...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure we could do that indeed

}
}
2 changes: 1 addition & 1 deletion Serializer/JMSSerializerAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ private function convertContext(Context $context, $direction)
}

foreach ($context->getAttributes() as $key => $value) {
$jmsContext->attributes->set($key, $value);
$jmsContext->setAttribute($key, $value);
}

if (null !== $context->getVersion()) {
Expand Down
19 changes: 10 additions & 9 deletions Serializer/Normalizer/ExceptionHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace FOS\RestBundle\Serializer\Normalizer;

use JMS\Serializer\Context;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\GraphNavigatorInterface;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\XmlSerializationVisitor;
Expand All @@ -26,13 +26,13 @@ public static function getSubscribingMethods()
{
return [
[
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
'format' => 'json',
'type' => \Exception::class,
'method' => 'serializeToJson',
],
[
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
'format' => 'xml',
'type' => \Exception::class,
'method' => 'serializeToXml',
Expand Down Expand Up @@ -73,12 +73,14 @@ public function serializeToXml(
) {
$data = $this->convertToArray($exception, $context);

if (null === $visitor->document) {
$visitor->document = $visitor->createDocument(null, null, true);
$document = $visitor->getDocument(true);

if (!$visitor->getCurrentNode()) {
$visitor->createRoot();
}

foreach ($data as $key => $value) {
$entryNode = $visitor->document->createElement($key);
$entryNode = $document->createElement($key);
$visitor->getCurrentNode()->appendChild($entryNode);
$visitor->setCurrentNode($entryNode);

Expand All @@ -101,9 +103,8 @@ protected function convertToArray(\Exception $exception, Context $context)
{
$data = [];

$templateData = $context->attributes->get('template_data');
if ($templateData->isDefined()) {
$templateData = $templateData->get();
if ($context->hasAttribute('template_data')) {
$templateData = $context->getAttribute('template_data');
if (array_key_exists('status_code', $templateData)) {
$data['code'] = $statusCode = $templateData['status_code'];
}
Expand Down
31 changes: 17 additions & 14 deletions Serializer/Normalizer/FormErrorHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use JMS\Serializer\Handler\FormErrorHandler as JMSFormErrorHandler;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\Visitor\SerializationVisitorInterface;
use JMS\Serializer\XmlSerializationVisitor;
use Symfony\Component\Form\Form;
use JMS\Serializer\YamlSerializationVisitor;
Expand All @@ -39,27 +40,30 @@ public static function getSubscribingMethods()
public function serializeFormToXml(XmlSerializationVisitor $visitor, Form $form, array $type, Context $context = null)
{
if ($context) {
$statusCode = $context->attributes->get('status_code');
if ($statusCode->isDefined()) {
if (null === $visitor->document) {
$visitor->document = $visitor->createDocument(null, null, true);
if ($context->hasAttribute('status_code')) {
$document = $visitor->getDocument(true);
if (!$visitor->getCurrentNode()) {
$visitor->createRoot();
}

$codeNode = $visitor->document->createElement('code');
$codeNode = $document->createElement('code');
$visitor->getCurrentNode()->appendChild($codeNode);
$codeNode->appendChild($context->getNavigator()->accept($statusCode->get(), null, $context));
$codeNode->appendChild($context->getNavigator()->accept($context->getAttribute('status_code'), null, $context));

$messageNode = $visitor->document->createElement('message');
$messageNode = $document->createElement('message');
$visitor->getCurrentNode()->appendChild($messageNode);
$messageNode->appendChild($context->getNavigator()->accept('Validation Failed', null, $context));

$errorsNode = $visitor->document->createElement('errors');
$errorsNode = $document->createElement('errors');
$visitor->getCurrentNode()->appendChild($errorsNode);
$visitor->setCurrentNode($errorsNode);
$this->formErrorHandler->serializeFormToXml($visitor, $form, $type);

$errorNodes = $this->formErrorHandler->serializeFormToXml($visitor, $form, $type);
$errorsNode->appendChild($errorNodes);

$visitor->revertCurrentNode();

return;
return $visitor->getCurrentNode();
}
}

Expand All @@ -68,7 +72,7 @@ public function serializeFormToXml(XmlSerializationVisitor $visitor, Form $form,

public function serializeFormToJson(JsonSerializationVisitor $visitor, Form $form, array $type, Context $context = null)
{
$isRoot = null === $visitor->getRoot();
$isRoot = !interface_exists(SerializationVisitorInterface::class) && null === $visitor->getRoot();
$result = $this->adaptFormArray($this->formErrorHandler->serializeFormToJson($visitor, $form, $type), $context);

if ($isRoot) {
Expand Down Expand Up @@ -115,9 +119,8 @@ private function getStatusCode(Context $context = null)
return;
}

$statusCode = $context->attributes->get('status_code');
if ($statusCode->isDefined()) {
return $statusCode->get();
if ($context->hasAttribute('status_code')) {
return $context->getAttribute('status_code');
}
}
}
11 changes: 9 additions & 2 deletions Tests/Functional/DependencyInjectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@

use FOS\RestBundle\FOSRestBundle;
use FOS\RestBundle\Serializer\JMSHandlerRegistry;
use FOS\RestBundle\Serializer\JMSHandlerRegistryV2;
use FOS\RestBundle\Serializer\Normalizer\FormErrorHandler;
use JMS\Serializer\Visitor\SerializationVisitorInterface;
use JMS\SerializerBundle\JMSSerializerBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
Expand All @@ -29,8 +31,12 @@ public function testSerializerRelatedServicesAreNotRemovedWhenJmsSerializerBundl
self::bootKernel();
$container = self::$kernel->getContainer();

$this->assertInstanceOf(FormErrorHandler::class, $container->get('jms_serializer.form_error_handler'));
$this->assertInstanceOf(JMSHandlerRegistry::class, $container->get('test.jms_serializer.handler_registry'));
$this->assertInstanceOf(FormErrorHandler::class, $container->get('test.jms_serializer.form_error_handler'));

$this->assertInstanceOf(
interface_exists(SerializationVisitorInterface::class) ? JMSHandlerRegistryV2::class : JMSHandlerRegistry::class,
$container->get('test.jms_serializer.handler_registry')
);
}

protected static function getKernelClass()
Expand Down Expand Up @@ -63,6 +69,7 @@ public function registerContainerConfiguration(LoaderInterface $loader)
'exception' => null,
]);
$container->setAlias('test.jms_serializer.handler_registry', new Alias('jms_serializer.handler_registry', true));
$container->setAlias('test.jms_serializer.form_error_handler', new Alias('jms_serializer.form_error_handler', true));
});
}

Expand Down
5 changes: 1 addition & 4 deletions Tests/Serializer/JMSSerializerAdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
use JMS\Serializer\Exclusion\ExclusionStrategyInterface;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerInterface;
use PhpCollection\MapInterface;
use PHPUnit\Framework\TestCase;

class JMSSerializerAdapterTest extends TestCase
Expand Down Expand Up @@ -94,15 +93,13 @@ public function testContextInfoAreConverted()
$exclusion = $this->getMockBuilder(ExclusionStrategyInterface::class)->getMock();

$jmsContext = $this->getMockBuilder(SerializationContext::class)->getMock();
$jmsContext->attributes = $this->getMockBuilder(MapInterface::class)->getMock();

$jmsContext->expects($this->once())->method('setGroups')->with(['foo']);
$jmsContext->expects($this->once())->method('setSerializeNull')->with(true);
$jmsContext->expects($this->once())->method('enableMaxDepthChecks');
$jmsContext->expects($this->once())->method('setVersion')->with('5.0.1');
$jmsContext->expects($this->once())->method('addExclusionStrategy')->with($exclusion);

$jmsContext->attributes->expects($this->once())->method('set')->with('foo', 'bar');
$jmsContext->expects($this->once())->method('setAttribute')->with('foo', 'bar');

$this->serializationContextFactory->method('createSerializationContext')->willReturn($jmsContext);

Expand Down
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,20 @@
"symfony/expression-language": "~2.7|^3.0|^4.0",
"symfony/css-selector": "^2.7|^3.0|^4.0",
"phpoption/phpoption": "^1.1",
"jms/serializer-bundle": "^1.2|^2.0",
"jms/serializer-bundle": "^2.0|^3.0",
"jms/serializer": "^1.13|^2.0",
"psr/http-message": "^1.0"
},
"suggest": {
"sensio/framework-extra-bundle": "Add support for the request body converter and the view response listener, requires ^3.0",
"jms/serializer-bundle": "Add support for advanced serialization capabilities, recommended, requires ^1.0",
"jms/serializer-bundle": "Add support for advanced serialization capabilities, recommended, requires ^2.0|^3.0",
"symfony/expression-language": "Add support for using the expression language in the routing, requires ^2.7|^3.0",
"symfony/serializer": "Add support for basic serialization capabilities and xml decoding, requires ^2.7|^3.0",
"symfony/validator": "Add support for validation capabilities in the ParamFetcher, requires ^2.7|^3.0"
},
"conflict": {
"sensio/framework-extra-bundle": "<3.0.13",
"jms/serializer-bundle": "<1.2.0",
"jms/serializer-bundle": "<2.0.0",
"jms/serializer": "1.3.0"
},
"extra": {
Expand Down