1<?php 2 3declare(strict_types=1); 4 5namespace JMS\Serializer\Handler; 6 7use JMS\Serializer\Exception\LogicException; 8use JMS\Serializer\Exception\RuntimeException; 9use JMS\Serializer\GraphNavigatorInterface; 10 11class HandlerRegistry implements HandlerRegistryInterface 12{ 13 /** 14 * @var callable[] 15 */ 16 protected $handlers; 17 18 public static function getDefaultMethod(int $direction, string $type, string $format): string 19 { 20 if (false !== $pos = strrpos($type, '\\')) { 21 $type = substr($type, $pos + 1); 22 } 23 24 switch ($direction) { 25 case GraphNavigatorInterface::DIRECTION_DESERIALIZATION: 26 return 'deserialize' . $type . 'From' . $format; 27 28 case GraphNavigatorInterface::DIRECTION_SERIALIZATION: 29 return 'serialize' . $type . 'To' . $format; 30 31 default: 32 throw new LogicException(sprintf('The direction %s does not exist; see GraphNavigatorInterface::DIRECTION_??? constants.', json_encode($direction))); 33 } 34 } 35 36 public function __construct(array $handlers = []) 37 { 38 $this->handlers = $handlers; 39 } 40 41 public function registerSubscribingHandler(SubscribingHandlerInterface $handler): void 42 { 43 foreach ($handler->getSubscribingMethods() as $methodData) { 44 if (!isset($methodData['type'], $methodData['format'])) { 45 throw new RuntimeException(sprintf('For each subscribing method a "type" and "format" attribute must be given, but only got "%s" for %s.', implode('" and "', array_keys($methodData)), \get_class($handler))); 46 } 47 48 $directions = [GraphNavigatorInterface::DIRECTION_DESERIALIZATION, GraphNavigatorInterface::DIRECTION_SERIALIZATION]; 49 if (isset($methodData['direction'])) { 50 $directions = [$methodData['direction']]; 51 } 52 53 foreach ($directions as $direction) { 54 $method = $methodData['method'] ?? self::getDefaultMethod($direction, $methodData['type'], $methodData['format']); 55 $this->registerHandler($direction, $methodData['type'], $methodData['format'], [$handler, $method]); 56 } 57 } 58 } 59 60 /** 61 * {@inheritdoc} 62 */ 63 public function registerHandler(int $direction, string $typeName, string $format, $handler): void 64 { 65 $this->handlers[$direction][$typeName][$format] = $handler; 66 } 67 68 /** 69 * {@inheritdoc} 70 */ 71 public function getHandler(int $direction, string $typeName, string $format) 72 { 73 if (!isset($this->handlers[$direction][$typeName][$format])) { 74 return null; 75 } 76 77 return $this->handlers[$direction][$typeName][$format]; 78 } 79} 80