Skip to content

Commit

Permalink
Add global handlers for all data types
Browse files Browse the repository at this point in the history
  • Loading branch information
MoviU committed Feb 20, 2025
1 parent 033c9be commit 2d6a6a0
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 6 deletions.
47 changes: 47 additions & 0 deletions doc/handlers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,50 @@ Skippable Subscribing Handlers

In case you need to be able to fall back to the default deserialization behavior instead of using your custom
handler, you can simply throw a `SkipHandlerException` from you custom handler method to do so.

Global Subscribing Handlers
----------------
You can register global handler, if type is '*'::

use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\JsonDeserializationVisitor;
use JMS\Serializer\Context;

class MyHandler implements SubscribingHandlerInterface
{
public static function getSubscribingMethods()
{
return [
[
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'format' => 'json',
'type' => '*',
'method' => 'handleCustomSerialization',
],
[
'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
'format' => 'json',
'type' => '*',
'method' => 'handleCustomDeserialization',
],
];
}

public function handleCustomSerialization(JsonSerializationVisitor $visitor, mixed $data, array $type, Context $context)
{
// preform custom logic
}

public function handleCustomDeserialization(JsonDeserializationVisitor $visitor, mixed $data, array $type, Context $context)
{
// preform custom logic
}
}
..
Be aware that when you register a global handler,
it will be triggered for every serialization/deserialization process,
unless another custom handler specified.
Be sure to properly handle data processing.
12 changes: 9 additions & 3 deletions src/Handler/HandlerRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

class HandlerRegistry implements HandlerRegistryInterface
{
protected const GLOBAL_HANDLER_TYPE = '*';

/**
* @var callable[]
*/
Expand Down Expand Up @@ -70,11 +72,15 @@ public function registerHandler(int $direction, string $typeName, string $format
*/
public function getHandler(int $direction, string $typeName, string $format)
{
if (!isset($this->handlers[$direction][$typeName][$format])) {
return null;
if (isset($this->handlers[$direction][$typeName][$format])) {
return $this->handlers[$direction][$typeName][$format];
}

if (isset($this->handlers[$direction][self::GLOBAL_HANDLER_TYPE][$format])) {
return $this->handlers[$direction][self::GLOBAL_HANDLER_TYPE][$format];
}

return $this->handlers[$direction][$typeName][$format];
return null;
}

/**
Expand Down
15 changes: 12 additions & 3 deletions src/Handler/LazyHandlerRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,20 @@ public function getHandler(int $direction, string $typeName, string $format)
return $this->initializedHandlers[$direction][$typeName][$format];
}

if (!isset($this->handlers[$direction][$typeName][$format])) {
return null;
$handler = $this->handlers[$direction][$typeName][$format] ?? null;

if (null === $handler) {
if (isset($this->initializedHandlers[$direction][self::GLOBAL_HANDLER_TYPE][$format])) {
return $this->initializedHandlers[$direction][self::GLOBAL_HANDLER_TYPE][$format];
}

if (null === $handler = $this->handlers[$direction][self::GLOBAL_HANDLER_TYPE][$format]) {
return null;
}

$typeName = self::GLOBAL_HANDLER_TYPE;
}

$handler = $this->handlers[$direction][$typeName][$format];
if (\is_array($handler) && \is_string($handler[0]) && $this->container->has($handler[0])) {
$handler[0] = $this->container->get($handler[0]);
}
Expand Down
20 changes: 20 additions & 0 deletions tests/Handler/HandlerRegistryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,26 @@ public function testRegisteredHandlersCanBeRetrieved()
self::assertSame($xmlDeserializationHandler, $this->handlerRegistry->getHandler(GraphNavigatorInterface::DIRECTION_DESERIALIZATION, '\stdClass', 'xml'));
}

public function testRegisteredGlobalHandlersCanBeRetrieved()
{
$jsonSerializationHandler = new DummyHandler();
$this->handlerRegistry->registerHandler(GraphNavigatorInterface::DIRECTION_SERIALIZATION, '*', 'json', $jsonSerializationHandler);

$jsonDeserializationHandler = new DummyHandler();
$this->handlerRegistry->registerHandler(GraphNavigatorInterface::DIRECTION_DESERIALIZATION, '*', 'json', $jsonDeserializationHandler);

$xmlSerializationHandler = new DummyHandler();
$this->handlerRegistry->registerHandler(GraphNavigatorInterface::DIRECTION_SERIALIZATION, '*', 'xml', $xmlSerializationHandler);

$xmlDeserializationHandler = new DummyHandler();
$this->handlerRegistry->registerHandler(GraphNavigatorInterface::DIRECTION_DESERIALIZATION, '*', 'xml', $xmlDeserializationHandler);

self::assertSame($jsonSerializationHandler, $this->handlerRegistry->getHandler(GraphNavigatorInterface::DIRECTION_SERIALIZATION, '*', 'json'));
self::assertSame($jsonDeserializationHandler, $this->handlerRegistry->getHandler(GraphNavigatorInterface::DIRECTION_DESERIALIZATION, '*', 'json'));
self::assertSame($xmlSerializationHandler, $this->handlerRegistry->getHandler(GraphNavigatorInterface::DIRECTION_SERIALIZATION, '*', 'xml'));
self::assertSame($xmlDeserializationHandler, $this->handlerRegistry->getHandler(GraphNavigatorInterface::DIRECTION_DESERIALIZATION, '*', 'xml'));
}

protected function createHandlerRegistry()
{
return new HandlerRegistry();
Expand Down
24 changes: 24 additions & 0 deletions tests/Handler/LazyHandlerRegistryTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,30 @@ public function testRegisteredHandlersCanBeRetrievedWhenBeingDefinedAsServices()
self::assertSame([$xmlDeserializationHandler, 'handle'], $this->handlerRegistry->getHandler(GraphNavigatorInterface::DIRECTION_DESERIALIZATION, '\stdClass', 'xml'));
}

public function testRegisteredGlobalHandlersCanBeRetrievedWhenBeingDefinedAsServices()
{
$jsonSerializationHandler = new HandlerService();
$this->registerHandlerService('handler.serialization.json', $jsonSerializationHandler);
$this->handlerRegistry->registerHandler(GraphNavigatorInterface::DIRECTION_SERIALIZATION, '*', 'json', ['handler.serialization.json', 'handle']);

$jsonDeserializationHandler = new HandlerService();
$this->registerHandlerService('handler.deserialization.json', $jsonDeserializationHandler);
$this->handlerRegistry->registerHandler(GraphNavigatorInterface::DIRECTION_DESERIALIZATION, '*', 'json', ['handler.deserialization.json', 'handle']);

$xmlSerializationHandler = new HandlerService();
$this->registerHandlerService('handler.serialization.xml', $xmlSerializationHandler);
$this->handlerRegistry->registerHandler(GraphNavigatorInterface::DIRECTION_SERIALIZATION, '*', 'xml', ['handler.serialization.xml', 'handle']);

$xmlDeserializationHandler = new HandlerService();
$this->registerHandlerService('handler.deserialization.xml', $xmlDeserializationHandler);
$this->handlerRegistry->registerHandler(GraphNavigatorInterface::DIRECTION_DESERIALIZATION, '*', 'xml', ['handler.deserialization.xml', 'handle']);

self::assertSame([$jsonSerializationHandler, 'handle'], $this->handlerRegistry->getHandler(GraphNavigatorInterface::DIRECTION_SERIALIZATION, '*', 'json'));
self::assertSame([$jsonDeserializationHandler, 'handle'], $this->handlerRegistry->getHandler(GraphNavigatorInterface::DIRECTION_DESERIALIZATION, '*', 'json'));
self::assertSame([$xmlSerializationHandler, 'handle'], $this->handlerRegistry->getHandler(GraphNavigatorInterface::DIRECTION_SERIALIZATION, '*', 'xml'));
self::assertSame([$xmlDeserializationHandler, 'handle'], $this->handlerRegistry->getHandler(GraphNavigatorInterface::DIRECTION_DESERIALIZATION, '*', 'xml'));
}

abstract protected function createContainer();

abstract protected function registerHandlerService($serviceId, $listener);
Expand Down

0 comments on commit 2d6a6a0

Please sign in to comment.