Skip to content

Commit

Permalink
use single array for sorting all the handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
goetas committed May 23, 2018
1 parent 5d2069e commit 43651ca
Showing 1 changed file with 51 additions and 90 deletions.
141 changes: 51 additions & 90 deletions DependencyInjection/Compiler/CustomHandlersPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,40 @@ public function process(ContainerBuilder $container)
{
$handlers = array();
$handlerServices = array();
foreach ($this->findAndSortTaggedHandlers($container) as $attrs) {
$direction = $attrs['direction'];
$reference = $attrs['reference'];
$id = (string)$reference;
$definition = $container->getDefinition($id);
$method = isset($attrs['method']) ? $attrs['method'] : HandlerRegistry::getDefaultMethod($direction, $attrs['type'], $attrs['format']);
if (class_exists(ServiceLocatorTagPass::class) || $definition->isPublic()) {
$handlerServices[$id] = $reference;
$handlers[$direction][$attrs['type']][$attrs['format']] = array($id, $method);
} else {
$handlers[$direction][$attrs['type']][$attrs['format']] = array($reference, $method);
foreach ($container->findTaggedServiceIds('jms_serializer.handler') as $id => $tags) {
foreach ($tags as $attrs) {
if (!isset($attrs['type'], $attrs['format'])) {
throw new \RuntimeException(sprintf('Each tag named "jms_serializer.handler" of service "%s" must have at least two attributes: "type" and "format".', $id));
}

$directions = array(GraphNavigator::DIRECTION_DESERIALIZATION, GraphNavigator::DIRECTION_SERIALIZATION);
if (isset($attrs['direction'])) {
if (!defined($directionConstant = 'JMS\Serializer\GraphNavigator::DIRECTION_' . strtoupper($attrs['direction']))) {
throw new \RuntimeException(sprintf('The direction "%s" of tag "jms_serializer.handler" of service "%s" does not exist.', $attrs['direction'], $id));
}

$directions = array(constant($directionConstant));
}

foreach ($directions as $direction) {
$method = isset($attrs['method']) ? $attrs['method'] : HandlerRegistry::getDefaultMethod($direction, $attrs['type'], $attrs['format']);
$priority = isset($attrs['priority']) ? intval($attrs['priority']) : 0;
$ref = new Reference($id);
if (class_exists(ServiceLocatorTagPass::class) || $container->getDefinition($id)->isPublic()) {
$handlerServices[$id] = $ref;
$handlers[] = array($direction, $attrs['type'], $attrs['format'], $priority, $id, $method);
} else {
$handlers[] = array($direction, $attrs['type'], $attrs['format'], $priority, $ref, $method);
}
}
}
}

foreach ($this->findAndSortTaggedServices('jms_serializer.subscribing_handler', $container) as $reference) {
$id = (string)$reference;
$definition = $container->getDefinition($id);
$class = $definition->getClass();
foreach ($container->findTaggedServiceIds('jms_serializer.subscribing_handler') as $id => $tags) {

$def = $container->getDefinition($id);
$class = $def->getClass();

$ref = new \ReflectionClass($class);
if (!$ref->implementsInterface('JMS\Serializer\Handler\SubscribingHandlerInterface')) {
throw new \RuntimeException(sprintf('The service "%s" must implement the SubscribingHandlerInterface.', $id));
Expand All @@ -49,97 +65,42 @@ public function process(ContainerBuilder $container)
}

foreach ($directions as $direction) {
$priority = isset($methodData['priority']) ? intval($methodData['priority']) : 0;
$method = isset($methodData['method']) ? $methodData['method'] : HandlerRegistry::getDefaultMethod($direction, $methodData['type'], $methodData['format']);
if (class_exists(ServiceLocatorTagPass::class) || $definition->isPublic()) {
$handlerServices[$id] = $reference;
$handlers[$direction][$methodData['type']][$methodData['format']] = array($id, $method);

$ref = new Reference($id);
if (class_exists(ServiceLocatorTagPass::class) || $def->isPublic()) {
$handlerServices[$id] = $ref;
$handlers[] = array($direction, $methodData['type'], $methodData['format'], $priority, $id, $method);
} else {
$handlers[$direction][$methodData['type']][$methodData['format']] = array($reference, $method);
$handlers[] = array($direction, $methodData['type'], $methodData['format'], $priority, $ref, $method);
}
}
}
}

$container->findDefinition('jms_serializer.handler_registry')->addArgument($handlers);
$handlers = $this->sortAndFlattenHandlersList($handlers);

$container->findDefinition('jms_serializer.handler_registry')
->addArgument($handlers);

if (class_exists(ServiceLocatorTagPass::class)) {
$serviceLocator = ServiceLocatorTagPass::register($container, $handlerServices);
$container->findDefinition('jms_serializer.handler_registry')->replaceArgument(0, $serviceLocator);
}
}

/**
* Finds all handler services with the given tag name and order them by their priority.
*
* @param ContainerBuilder $container
*
* @return Reference[]
*/
private function findAndSortTaggedHandlers(ContainerBuilder $container)
{
$services = array();

foreach ($container->findTaggedServiceIds('jms_serializer.handler', true) as $serviceId => $attributeList) {
foreach ($attributeList as $attributes) {
if (!isset($attributes['type'], $attributes['format'])) {
throw new \RuntimeException(sprintf('Each tag named "jms_serializer.handler" of service "%s" must have at least two attributes: "type" and "format".', $serviceId));
}

$directions = array(GraphNavigator::DIRECTION_DESERIALIZATION, GraphNavigator::DIRECTION_SERIALIZATION);
if (isset($attributes['direction'])) {
if (!defined($directionConstant = 'JMS\Serializer\GraphNavigator::DIRECTION_' . strtoupper($attributes['direction']))) {
throw new \RuntimeException(sprintf('The direction "%s" of tag "jms_serializer.handler" of service "%s" does not exist.', $attributes['direction'], $serviceId));
}

$directions = array(constant($directionConstant));
}

$priority = isset($attributes[0]['priority']) ? intval($attributes[0]['priority']) : 0;
foreach ($directions as $direction) {
$services[$direction . $attributes['type'] . $attributes['format']][$priority][] = array_merge(
$attributes,
[
'direction' => $direction,
'reference' => new Reference($serviceId)
]
);
}
}
}

if ($services) {
foreach ($services as $combination => $handlers) {
krsort($handlers);
$services[$combination] = array_reverse(call_user_func_array('array_merge', $handlers))[0];
}
}

return $services;
}

/**
* Finds all services with the given tag name and order them by their priority.
*
* @param string $tagName
* @param ContainerBuilder $container
*
* @return Reference[]
*/
private function findAndSortTaggedServices($tagName, ContainerBuilder $container)
private function sortAndFlattenHandlersList(array $allHandlers)
{
$services = array();

foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) {
$priority = isset($attributes[0]['priority']) ? intval($attributes[0]['priority']) : 0;

$services[$priority][] = new Reference($serviceId);
}

if ($services) {
krsort($services);
$services = call_user_func_array('array_merge', $services);
uasort($allHandlers, function ($a, $b) {
return $b[3] > $a[3] ? 1 : -1;
});
$handlers = [];
foreach ($allHandlers as $handler) {
list ($direction, $type, $format, $priority, $service, $method) = $handler;
$handlers[$direction][$type][$format] = [$service, $method];
}

return $services;
return $handlers;
}
}

0 comments on commit 43651ca

Please sign in to comment.