vendor/jms/serializer/src/EventDispatcher/Subscriber/DoctrineProxySubscriber.php line 101

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace JMS\Serializer\EventDispatcher\Subscriber;
  4. use Doctrine\Common\Persistence\Proxy as LegacyProxy;
  5. use Doctrine\ODM\MongoDB\PersistentCollection as MongoDBPersistentCollection;
  6. use Doctrine\ODM\PHPCR\PersistentCollection as PHPCRPersistentCollection;
  7. use Doctrine\ORM\PersistentCollection;
  8. use Doctrine\Persistence\Proxy;
  9. use JMS\Serializer\EventDispatcher\EventDispatcherInterface;
  10. use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
  11. use JMS\Serializer\EventDispatcher\PreSerializeEvent;
  12. use ProxyManager\Proxy\LazyLoadingInterface;
  13. final class DoctrineProxySubscriber implements EventSubscriberInterface
  14. {
  15.     /**
  16.      * @var bool
  17.      */
  18.     private $skipVirtualTypeInit;
  19.     /**
  20.      * @var bool
  21.      */
  22.     private $initializeExcluded;
  23.     public function __construct(bool $skipVirtualTypeInit truebool $initializeExcluded false)
  24.     {
  25.         $this->skipVirtualTypeInit $skipVirtualTypeInit;
  26.         $this->initializeExcluded $initializeExcluded;
  27.     }
  28.     public function onPreSerialize(PreSerializeEvent $event): void
  29.     {
  30.         $object $event->getObject();
  31.         $type $event->getType();
  32.         // If the set type name is not an actual class, but a faked type for which a custom handler exists, we do not
  33.         // modify it with this subscriber. Also, we forgo autoloading here as an instance of this type is already created,
  34.         // so it must be loaded if its a real class.
  35.         $virtualType = !class_exists($type['name'], false);
  36.         if (
  37.             $object instanceof PersistentCollection
  38.             || $object instanceof MongoDBPersistentCollection
  39.             || $object instanceof PHPCRPersistentCollection
  40.         ) {
  41.             if (!$virtualType) {
  42.                 $event->setType('ArrayCollection');
  43.             }
  44.             return;
  45.         }
  46.         if (
  47.             ($this->skipVirtualTypeInit && $virtualType) ||
  48.             (!$object instanceof Proxy && !$object instanceof LazyLoadingInterface)
  49.         ) {
  50.             return;
  51.         }
  52.         // do not initialize the proxy if is going to be excluded by-class by some exclusion strategy
  53.         if (false === $this->initializeExcluded && !$virtualType) {
  54.             $context $event->getContext();
  55.             $exclusionStrategy $context->getExclusionStrategy();
  56.             $metadata $context->getMetadataFactory()->getMetadataForClass(get_parent_class($object));
  57.             if (null !== $metadata && null !== $exclusionStrategy && $exclusionStrategy->shouldSkipClass($metadata$context)) {
  58.                 return;
  59.             }
  60.         }
  61.         if ($object instanceof LazyLoadingInterface) {
  62.             $object->initializeProxy();
  63.         } else {
  64.             $object->__load();
  65.         }
  66.         if (!$virtualType) {
  67.             $event->setType(get_parent_class($object), $type['params']);
  68.         }
  69.     }
  70.     public function onPreSerializeTypedProxy(PreSerializeEvent $eventstring $eventNamestring $classstring $formatEventDispatcherInterface $dispatcher): void
  71.     {
  72.         $type $event->getType();
  73.         // is a virtual type? then there is no need to change the event name
  74.         if (!class_exists($type['name'], false)) {
  75.             return;
  76.         }
  77.         $object $event->getObject();
  78.         if ($object instanceof Proxy) {
  79.             $parentClassName get_parent_class($object);
  80.             // check if this is already a re-dispatch
  81.             if (strtolower($class) !== strtolower($parentClassName)) {
  82.                 $event->stopPropagation();
  83.                 $newEvent = new PreSerializeEvent($event->getContext(), $object, ['name' => $parentClassName'params' => $type['params']]);
  84.                 $dispatcher->dispatch($eventName$parentClassName$format$newEvent);
  85.                 // update the type in case some listener changed it
  86.                 $newType $newEvent->getType();
  87.                 $event->setType($newType['name'], $newType['params']);
  88.             }
  89.         }
  90.     }
  91.     /**
  92.      * {@inheritdoc}
  93.      */
  94.     public static function getSubscribedEvents()
  95.     {
  96.         return [
  97.             ['event' => 'serializer.pre_serialize''method' => 'onPreSerializeTypedProxy''interface' => Proxy::class],
  98.             ['event' => 'serializer.pre_serialize''method' => 'onPreSerializeTypedProxy''interface' => LegacyProxy::class],
  99.             ['event' => 'serializer.pre_serialize''method' => 'onPreSerialize''interface' => PersistentCollection::class],
  100.             ['event' => 'serializer.pre_serialize''method' => 'onPreSerialize''interface' => MongoDBPersistentCollection::class],
  101.             ['event' => 'serializer.pre_serialize''method' => 'onPreSerialize''interface' => PHPCRPersistentCollection::class],
  102.             ['event' => 'serializer.pre_serialize''method' => 'onPreSerialize''interface' => Proxy::class],
  103.             ['event' => 'serializer.pre_serialize''method' => 'onPreSerialize''interface' => LegacyProxy::class],
  104.             ['event' => 'serializer.pre_serialize''method' => 'onPreSerialize''interface' => LazyLoadingInterface::class],
  105.         ];
  106.     }
  107. }