RegisterEventListenersAndSubscribersPass.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. <?php
  2. namespace JMS\SerializerBundle\DependencyInjection\Compiler;
  3. use JMS\SerializerBundle\Serializer\EventDispatcher\EventDispatcher;
  4. use JMS\SerializerBundle\Serializer\EventDispatcher\EventSubscriberInterface;
  5. use Symfony\Component\DependencyInjection\ContainerBuilder;
  6. use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
  7. class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
  8. {
  9. public function process(ContainerBuilder $container)
  10. {
  11. $listeners = array();
  12. foreach ($container->findTaggedServiceIds('jms_serializer.event_listener') as $id => $tags) {
  13. if (!$container->getDefinition($id)->isPublic()) {
  14. throw new \RuntimeException(sprintf('The tag "jms_serializer.event_listener" of service "%s" requires the service to be public.', $id));
  15. }
  16. foreach ($tags as $attributes) {
  17. if ( ! isset($attributes['event'])) {
  18. throw new \RuntimeException(sprintf('The tag "jms_serializer.event_listener" of service "%s" requires an attribute named "event".', $id));
  19. }
  20. $class = isset($attributes['class']) ? strtolower($attributes['class']) : null;
  21. $format = isset($attributes['format']) ? $attributes['format'] : null;
  22. $method = isset($attributes['method']) ? $attributes['method'] : EventDispatcher::getDefaultMethodName($attributes['event']);
  23. $priority = isset($attributes['priority']) ? (integer) $attributes['priority'] : 0;
  24. $listeners[$attributes['event']][$priority][] = array(array($id, $method), $class, $format);
  25. }
  26. }
  27. foreach ($container->findTaggedServiceIds('jms_serializer.event_subscriber') as $id => $tags) {
  28. $subscriberDefinition = $container->getDefinition($id);
  29. $subscriberClass = $container->getDefinition($id)->getClass();
  30. $subscriberClassReflectionObj = new \ReflectionClass($subscriberClass);
  31. if ( ! $subscriberClassReflectionObj->implementsInterface('JMS\SerializerBundle\Serializer\EventDispatcher\EventSubscriberInterface') ) {
  32. throw new \RuntimeException(sprintf('The service "%s" (class: %s) does not implement the EventSubscriberInterface.', $id, $subscriberClass));
  33. }
  34. if (!$subscriberDefinition->isPublic()) {
  35. throw new \RuntimeException(sprintf('The tag "jms_serializer.event_listener" of service "%s" requires the service to be public.', $id));
  36. }
  37. foreach (call_user_func(array($subscriberClass, 'getSubscribedEvents')) as $eventData) {
  38. if ( ! isset($eventData['event'])) {
  39. throw new \RuntimeException(sprintf('The service "%s" (class: %s) must return an event for each subscribed event.', $id, $subscriberClass));
  40. }
  41. $class = isset($eventData['class']) ? strtolower($eventData['class']) : null;
  42. $format = isset($eventData['format']) ? $eventData['format'] : null;
  43. $method = isset($eventData['method']) ? $eventData['method'] : EventDispatcher::getDefaultMethodName($eventData['event']);
  44. $priority = isset($attributes['priority']) ? (integer) $attributes['priority'] : 0;
  45. $listeners[$eventData['event']][$priority][] = array(array($id, $method), $class, $format);
  46. }
  47. }
  48. if ($listeners) {
  49. array_walk($listeners, function (&$value, $key) {
  50. ksort($value);
  51. });
  52. foreach ($listeners as &$events) {
  53. $events = call_user_func_array('array_merge', $events);
  54. }
  55. $container->getDefinition('jms_serializer.event_dispatcher')
  56. ->addMethodCall('setListeners', array($listeners));
  57. }
  58. }
  59. }