partkeepr

fork of partkeepr
git clone https://git.e1e0.net/partkeepr.git
Log | Files | Refs | Submodules | README | LICENSE

TemporaryFileEventListener.php (7053B)


      1 <?php
      2 
      3 namespace PartKeepr\UploadedFileBundle\EventListener;
      4 
      5 use Doctrine\Common\Annotations\Reader;
      6 use Dunglas\ApiBundle\Api\IriConverterInterface;
      7 use PartKeepr\ImageBundle\Entity\Image;
      8 use PartKeepr\ImageBundle\Entity\TempImage;
      9 use PartKeepr\ImageBundle\Services\ImageService;
     10 use PartKeepr\UploadedFileBundle\Entity\TempUploadedFile;
     11 use PartKeepr\UploadedFileBundle\Entity\UploadedFile;
     12 use PartKeepr\UploadedFileBundle\Services\UploadedFileService;
     13 use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
     14 use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
     15 
     16 class TemporaryFileEventListener
     17 {
     18     /**
     19      * @var UploadedFileService
     20      */
     21     private $uploadedFileService;
     22 
     23     /**
     24      * @var ImageService
     25      */
     26     private $imageService;
     27 
     28     /**
     29      * @var Reader
     30      */
     31     private $reader;
     32 
     33     /**
     34      * @var PropertyAccessorInterface
     35      */
     36     private $propertyAccessor;
     37 
     38     /**
     39      * @var IriConverterInterface
     40      */
     41     private $iriConverter;
     42 
     43     public function __construct(
     44         UploadedFileService $uploadedFileService,
     45         ImageService $imageService,
     46         Reader $reader,
     47         PropertyAccessorInterface $propertyAccessor,
     48         IriConverterInterface $iriConverter
     49     ) {
     50         $this->uploadedFileService = $uploadedFileService;
     51         $this->imageService = $imageService;
     52         $this->reader = $reader;
     53         $this->propertyAccessor = $propertyAccessor;
     54         $this->iriConverter = $iriConverter;
     55     }
     56 
     57     /**
     58      * Replaces any temporary images with actual instances of the configured UploadedFile collection.
     59      *
     60      * Automatically extracts the proper setters and getters from the metadata and instantiates the correct
     61      * UploadedFile child class.
     62      *
     63      * @param GetResponseForControllerResultEvent $event The event
     64      */
     65     public function replaceTemporaryFile(GetResponseForControllerResultEvent $event)
     66     {
     67         $data = $event->getControllerResult();
     68 
     69         if (!is_object($data)) {
     70             return;
     71         }
     72 
     73         $classReflection = new \ReflectionClass($data);
     74 
     75         foreach ($classReflection->getProperties() as $property) {
     76             $propertyAnnotationCollection = $this->reader->getPropertyAnnotation(
     77                 $property,
     78                 'PartKeepr\UploadedFileBundle\Annotation\UploadedFileCollection'
     79             );
     80 
     81             $propertyAnnotation = $this->reader->getPropertyAnnotation(
     82                 $property,
     83                 'PartKeepr\UploadedFileBundle\Annotation\UploadedFile'
     84             );
     85 
     86             $manyToOneAnnotation = $this->reader->getPropertyAnnotation(
     87                 $property,
     88                 'Doctrine\ORM\Mapping\OneToMany'
     89             );
     90 
     91             $oneToOneAnnotation = $this->reader->getPropertyAnnotation(
     92                 $property,
     93                 'Doctrine\ORM\Mapping\OneToOne'
     94             );
     95 
     96             if ($propertyAnnotationCollection !== null || $propertyAnnotation !== null) {
     97                 if ($manyToOneAnnotation !== null) {
     98                     $collection = $this->propertyAccessor->getValue($data, $property->getName());
     99 
    100                     foreach ($collection as $key => $item) {
    101                         if ($item instanceof TempUploadedFile || $item instanceof TempImage) {
    102                             $targetEntity = $manyToOneAnnotation->targetEntity;
    103 
    104                             $newFile = $this->setReplacementFile($targetEntity, $item, $data);
    105                             $collection[$key] = $newFile;
    106                         }
    107                     }
    108 
    109                     $this->propertyAccessor->setValue($data, $property->getName(), $collection);
    110                 }
    111 
    112                 if ($oneToOneAnnotation !== null) {
    113                     $item = $this->propertyAccessor->getValue($data, $property->getName());
    114 
    115                     if ($item instanceof TempUploadedFile || $item instanceof TempImage) {
    116                         $targetEntity = $oneToOneAnnotation->targetEntity;
    117 
    118                         $newFile = $this->setReplacementFile($targetEntity, $item, $data);
    119 
    120                         $this->propertyAccessor->setValue($data, $property->getName(), $newFile);
    121                     } else {
    122                         $item = $this->propertyAccessor->getValue($data, $property->getName());
    123 
    124                         if ($item !== null && $item->getReplacement() !== null) {
    125                             /**
    126                              * @var UploadedFile
    127                              */
    128                             $tempImage = $this->iriConverter->getItemFromIri($item->getReplacement());
    129                             $this->replaceFile($item, $tempImage);
    130                         }
    131                     }
    132                 }
    133             }
    134         }
    135 
    136         $event->setControllerResult($data);
    137     }
    138 
    139     /**
    140      * Replaces the TemporaryUploadedFile or TempImage with the actual instance. Automatically sets the
    141      * reference to the owning entity.
    142      *
    143      * @param string                     $targetEntity The entity to create
    144      * @param TempUploadedFile|TempImage $source       The source entity
    145      * @param object                     $target       The entity where to set the property
    146      *
    147      * @return object The newly created object instance
    148      */
    149     protected function setReplacementFile($targetEntity, $source, $target)
    150     {
    151         /**
    152          * @var UploadedFile
    153          */
    154         $newFile = new $targetEntity();
    155 
    156         $this->replaceFile($newFile, $source);
    157 
    158         $setterName = $this->getReferenceSetter($newFile, $target);
    159 
    160         if ($setterName !== false) {
    161             $this->propertyAccessor->setValue($newFile, $setterName, $target);
    162         }
    163 
    164         return $newFile;
    165     }
    166 
    167     protected function replaceFile(UploadedFile $target, UploadedFile $source)
    168     {
    169         if ($target instanceof Image) {
    170             $this->imageService->replaceFromUploadedFile($target, $source);
    171         } else {
    172             $this->uploadedFileService->replaceFromUploadedFile($target, $source);
    173         }
    174         $target->setDescription($source->getDescription());
    175     }
    176 
    177     /**
    178      * Returns the setter name for the inverse side.
    179      *
    180      * @param $inverseSideEntity
    181      * @param $owningSideEntity
    182      *
    183      * @return bool|string
    184      */
    185     protected function getReferenceSetter($inverseSideEntity, $owningSideEntity)
    186     {
    187         $inverseSideReflection = new \ReflectionClass($inverseSideEntity);
    188         $owningSideReflection = new \ReflectionClass($owningSideEntity);
    189 
    190         foreach ($inverseSideReflection->getProperties() as $inverseSideProperty) {
    191             $oneToManyAssociation = $this->reader->getPropertyAnnotation(
    192                 $inverseSideProperty,
    193                 'Doctrine\ORM\Mapping\ManyToOne'
    194             );
    195 
    196             if ($oneToManyAssociation !== null &&
    197                 $oneToManyAssociation->targetEntity == $owningSideReflection->getName()
    198             ) {
    199                 return $inverseSideProperty->getName();
    200             }
    201         }
    202 
    203         return false;
    204     }
    205 }