src/EventSubscriber/PreDtoValidationEventSubscriber.php line 19

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use App\Criteria\Interface\NormalizableDtoValueInterface;
  4. use Artyum\RequestDtoMapperBundle\Event\PreDtoValidationEvent;
  5. use DateTime;
  6. use LogicException;
  7. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  8. use Symfony\Component\PropertyAccess\PropertyAccess;
  9. use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
  10. use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
  11. use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
  12. use Symfony\Component\PropertyInfo\Type;
  13. use Throwable;
  14. class PreDtoValidationEventSubscriber implements EventSubscriberInterface
  15. {
  16.     public function onPreDtoValidationEvent(PreDtoValidationEvent $event): void
  17.     {
  18.         $dto $event->getSubject();
  19.         if (!($dto instanceof NormalizableDtoValueInterface)) {
  20.             return;
  21.         }
  22.         $phpDocExtractor = new PhpDocExtractor();
  23.         $reflectionExtractor = new ReflectionExtractor();
  24.         $listExtractors = [$reflectionExtractor];
  25.         $typeExtractors = [$phpDocExtractor$reflectionExtractor];
  26.         $propertyInfo = new PropertyInfoExtractor($listExtractors$typeExtractors);
  27.         $propertyAccessor PropertyAccess::createPropertyAccessor();
  28.         foreach ($propertyInfo->getProperties($dto::class) as $property) {
  29.             $types $propertyInfo->getTypes($dto::class, $property);
  30.             if (!$types) {
  31.                 continue;
  32.             }
  33.             if (count($types) > 1) {
  34.                 throw new LogicException('This subscriber only support properties with one type-hint.');
  35.             }
  36.             /** @var Type $expectedType */
  37.             $expectedType current($types);
  38.             if (!$propertyAccessor->isWritable($dto$property)) {
  39.                 throw new LogicException(sprintf('The property "%s" is not writable.'$property));
  40.             }
  41.             $value $propertyAccessor->getValue($dto$property);
  42.             if ($value === null || $value === '') {
  43.                 $propertyAccessor->setValue($dto$propertynull);
  44.                 continue;
  45.             }
  46.             switch ($expectedType->getBuiltinType()) {
  47.                 case 'bool':
  48.                     if (in_array($value, ['1''true'], true)) {
  49.                         $propertyAccessor->setValue($dto$propertytrue);
  50.                     }
  51.                     if (in_array($value, ['0''false'], true)) {
  52.                         $propertyAccessor->setValue($dto$propertyfalse);
  53.                     }
  54.                     break;
  55.                 case 'int':
  56.                     if (is_numeric($value)) {
  57.                         $propertyAccessor->setValue($dto$property, (int) $value);
  58.                     }
  59.                     break;
  60.                 case 'object':
  61.                     if ($expectedType->getClassName() === DateTime::class) {
  62.                         try {
  63.                             $propertyAccessor->setValue($dto$property, new DateTime($value));
  64.                         } catch (Throwable) {
  65.                             break;
  66.                         }
  67.                     }
  68.                     break;
  69.             }
  70.         }
  71.     }
  72.     public static function getSubscribedEvents(): array
  73.     {
  74.         return [
  75.             PreDtoValidationEvent::class => 'onPreDtoValidationEvent',
  76.         ];
  77.     }
  78. }