vendor/jms/serializer-bundle/DependencyInjection/Compiler/CustomHandlersPass.php line 52

Open in your IDE?
  1. <?php
  2. namespace JMS\SerializerBundle\DependencyInjection\Compiler;
  3. use JMS\Serializer\GraphNavigator;
  4. use JMS\Serializer\Handler\HandlerRegistry;
  5. use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
  6. use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
  7. use Symfony\Component\DependencyInjection\ContainerBuilder;
  8. use Symfony\Component\DependencyInjection\Reference;
  9. class CustomHandlersPass implements CompilerPassInterface
  10. {
  11.     public function process(ContainerBuilder $container)
  12.     {
  13.         $handlers = array();
  14.         $handlerServices = array();
  15.         foreach ($container->findTaggedServiceIds('jms_serializer.handler') as $id => $tags) {
  16.             foreach ($tags as $attrs) {
  17.                 if (!isset($attrs['type'], $attrs['format'])) {
  18.                     throw new \RuntimeException(sprintf('Each tag named "jms_serializer.handler" of service "%s" must have at least two attributes: "type" and "format".'$id));
  19.                 }
  20.                 $directions = array(GraphNavigator::DIRECTION_DESERIALIZATIONGraphNavigator::DIRECTION_SERIALIZATION);
  21.                 if (isset($attrs['direction'])) {
  22.                     if (!defined($directionConstant 'JMS\Serializer\GraphNavigator::DIRECTION_' strtoupper($attrs['direction']))) {
  23.                         throw new \RuntimeException(sprintf('The direction "%s" of tag "jms_serializer.handler" of service "%s" does not exist.'$attrs['direction'], $id));
  24.                     }
  25.                     $directions = array(constant($directionConstant));
  26.                 }
  27.                 foreach ($directions as $direction) {
  28.                     $method = isset($attrs['method']) ? $attrs['method'] : HandlerRegistry::getDefaultMethod($direction$attrs['type'], $attrs['format']);
  29.                     $priority = isset($attrs['priority']) ? intval($attrs['priority']) : 0;
  30.                     $ref = new Reference($id);
  31.                     if (class_exists(ServiceLocatorTagPass::class) || $container->getDefinition($id)->isPublic()) {
  32.                         $handlerServices[$id] = $ref;
  33.                         $handlers[] = array($direction$attrs['type'], $attrs['format'], $priority$id$method);
  34.                     } else {
  35.                         $handlers[] = array($direction$attrs['type'], $attrs['format'], $priority$ref$method);
  36.                     }
  37.                 }
  38.             }
  39.         }
  40.         foreach ($container->findTaggedServiceIds('jms_serializer.subscribing_handler') as $id => $tags) {
  41.             $def $container->getDefinition($id);
  42.             $class $def->getClass();
  43.             $ref = new \ReflectionClass($class);
  44.             if (!$ref->implementsInterface('JMS\Serializer\Handler\SubscribingHandlerInterface')) {
  45.                 throw new \RuntimeException(sprintf('The service "%s" must implement the SubscribingHandlerInterface.'$id));
  46.             }
  47.             foreach (call_user_func(array($class'getSubscribingMethods')) as $methodData) {
  48.                 if (!isset($methodData['format'], $methodData['type'])) {
  49.                     throw new \RuntimeException(sprintf('Each method returned from getSubscribingMethods of service "%s" must have a "type", and "format" attribute.'$id));
  50.                 }
  51.                 $directions = array(GraphNavigator::DIRECTION_DESERIALIZATIONGraphNavigator::DIRECTION_SERIALIZATION);
  52.                 if (isset($methodData['direction'])) {
  53.                     $directions = array($methodData['direction']);
  54.                 }
  55.                 foreach ($directions as $direction) {
  56.                     $priority = isset($methodData['priority']) ? intval($methodData['priority']) : 0;
  57.                     $method = isset($methodData['method']) ? $methodData['method'] : HandlerRegistry::getDefaultMethod($direction$methodData['type'], $methodData['format']);
  58.                     $ref = new Reference($id);
  59.                     if (class_exists(ServiceLocatorTagPass::class) || $def->isPublic()) {
  60.                         $handlerServices[$id] = $ref;
  61.                         $handlers[] = array($direction$methodData['type'], $methodData['format'], $priority$id$method);
  62.                     } else {
  63.                         $handlers[] = array($direction$methodData['type'], $methodData['format'], $priority$ref$method);
  64.                     }
  65.                 }
  66.             }
  67.         }
  68.         $handlers $this->sortAndFlattenHandlersList($handlers);
  69.         $container->findDefinition('jms_serializer.handler_registry')
  70.             ->addArgument($handlers);
  71.         if (class_exists(ServiceLocatorTagPass::class)) {
  72.             $serviceLocator ServiceLocatorTagPass::register($container$handlerServices);
  73.             $container->findDefinition('jms_serializer.handler_registry')->replaceArgument(0$serviceLocator);
  74.         }
  75.     }
  76.     private function sortAndFlattenHandlersList(array $allHandlers)
  77.     {
  78.         $sorter = function ($a$b) {
  79.             return $b[3] == $a[3] ? : ($b[3] > $a[3] ? : -1);
  80.         };
  81.         self::stable_uasort($allHandlers$sorter);
  82.         $handlers = [];
  83.         foreach ($allHandlers as $handler) {
  84.             list ($direction$type$format$priority$service$method) = $handler;
  85.             $handlers[$direction][$type][$format] = [$service$method];
  86.         }
  87.         return $handlers;
  88.     }
  89.     /**
  90.      * Performs stable sorting. Copied from http://php.net/manual/en/function.uasort.php#121283
  91.      *
  92.      * @param array $array
  93.      * @param $value_compare_func
  94.      * @return bool
  95.      */
  96.     private static function stable_uasort(array &$array$value_compare_func)
  97.     {
  98.         $index 0;
  99.         foreach ($array as &$item) {
  100.             $item = array($index++, $item);
  101.         }
  102.         $result uasort($array, function ($a$b) use ($value_compare_func) {
  103.             $result call_user_func($value_compare_func$a[1], $b[1]);
  104.             return $result == $a[0] - $b[0] : $result;
  105.         });
  106.         foreach ($array as &$item) {
  107.             $item $item[1];
  108.         }
  109.         return $result;
  110.     }
  111. }