vendor/vich/uploader-bundle/src/Mapping/PropertyMappingFactory.php line 115

Open in your IDE?
  1. <?php
  2. namespace Vich\UploaderBundle\Mapping;
  3. use Doctrine\Persistence\Proxy;
  4. use Symfony\Component\DependencyInjection\ContainerInterface;
  5. use Vich\UploaderBundle\Exception\MappingNotFoundException;
  6. use Vich\UploaderBundle\Exception\NotUploadableException;
  7. use Vich\UploaderBundle\Metadata\MetadataReader;
  8. use Vich\UploaderBundle\Naming\ConfigurableInterface;
  9. use Vich\UploaderBundle\Util\ClassUtils;
  10. /**
  11.  * PropertyMappingFactory.
  12.  *
  13.  * @author Dustin Dobervich <ddobervich@gmail.com>
  14.  */
  15. class PropertyMappingFactory
  16. {
  17.     /**
  18.      * @var ContainerInterface
  19.      */
  20.     protected $container;
  21.     /**
  22.      * @var MetadataReader
  23.      */
  24.     protected $metadata;
  25.     /**
  26.      * @var array
  27.      */
  28.     protected $mappings;
  29.     /**
  30.      * @var string
  31.      */
  32.     protected $defaultFilenameAttributeSuffix;
  33.     public function __construct(ContainerInterface $containerMetadataReader $metadata, array $mappings, ?string $defaultFilenameAttributeSuffix '_name')
  34.     {
  35.         $this->container $container;
  36.         $this->metadata $metadata;
  37.         $this->mappings $mappings;
  38.         $this->defaultFilenameAttributeSuffix $defaultFilenameAttributeSuffix;
  39.     }
  40.     /**
  41.      * Creates an array of PropetyMapping objects which contain the
  42.      * configuration for the uploadable fields in the specified
  43.      * object.
  44.      *
  45.      * @param object      $obj         The object
  46.      * @param string|null $className   The object's class. Mandatory if $obj can't be used to determine it
  47.      * @param string|null $mappingName The mapping name
  48.      *
  49.      * @return array|PropertyMapping[] An array up PropertyMapping objects
  50.      *
  51.      * @throws \RuntimeException
  52.      * @throws MappingNotFoundException
  53.      * @throws NotUploadableException
  54.      */
  55.     public function fromObject($obj, ?string $className null, ?string $mappingName null): array
  56.     {
  57.         if ($obj instanceof Proxy) {
  58.             $obj->__load();
  59.         }
  60.         $class $this->getClassName($obj$className);
  61.         $this->checkUploadable($class);
  62.         $mappings = [];
  63.         foreach ($this->metadata->getUploadableFields($class) as $field => $mappingData) {
  64.             if (null !== $mappingName && $mappingName !== $mappingData['mapping']) {
  65.                 continue;
  66.             }
  67.             $mappings[] = $this->createMapping($obj$field$mappingData);
  68.         }
  69.         return $mappings;
  70.     }
  71.     /**
  72.      * Creates a property mapping object which contains the
  73.      * configuration for the specified uploadable field.
  74.      *
  75.      * @param object|array $obj       The object
  76.      * @param string       $field     The field
  77.      * @param string|null  $className The object's class. Mandatory if $obj can't be used to determine it
  78.      *
  79.      * @return PropertyMapping|null The property mapping
  80.      *
  81.      * @throws \RuntimeException
  82.      * @throws MappingNotFoundException
  83.      * @throws NotUploadableException
  84.      */
  85.     public function fromField($objstring $field, ?string $className null): ?PropertyMapping
  86.     {
  87.         if ($obj instanceof Proxy) {
  88.             $obj->__load();
  89.         }
  90.         $class $this->getClassName($obj$className);
  91.         $this->checkUploadable($class);
  92.         $mappingData $this->metadata->getUploadableField($class$field);
  93.         if (null === $mappingData) {
  94.             return null;
  95.         }
  96.         return $this->createMapping($obj$field$mappingData);
  97.     }
  98.     public function fromFirstField(object $obj, ?string $className null): ?PropertyMapping
  99.     {
  100.         if ($obj instanceof Proxy) {
  101.             $obj->__load();
  102.         }
  103.         $class $this->getClassName($obj$className);
  104.         $this->checkUploadable($class);
  105.         $mappingData $this->metadata->getUploadableFields($class);
  106.         if (=== \count($mappingData)) {
  107.             return null;
  108.         }
  109.         return $this->createMapping($obj\key($mappingData), \reset($mappingData));
  110.     }
  111.     /**
  112.      * Checks to see if the class is uploadable.
  113.      *
  114.      * @param string $class The class name (FQCN)
  115.      *
  116.      * @throws NotUploadableException
  117.      */
  118.     protected function checkUploadable(string $class): void
  119.     {
  120.         if (!$this->metadata->isUploadable($class)) {
  121.             throw new NotUploadableException(\sprintf('The class "%s" is not uploadable. If you use annotations to configure VichUploaderBundle, you probably just forgot to add `@Vich\Uploadable` on top of your entity. If you don\'t use annotations, check that the configuration files are in the right place. In both cases, clearing the cache can also solve the issue.'$class));
  122.         }
  123.     }
  124.     /**
  125.      * Creates the property mapping from the read annotation and configured mapping.
  126.      *
  127.      * @param object $obj         The object
  128.      * @param string $fieldName   The field name
  129.      * @param array  $mappingData The mapping data
  130.      *
  131.      * @return PropertyMapping The property mapping
  132.      *
  133.      * @throws \LogicException
  134.      * @throws MappingNotFoundException
  135.      */
  136.     protected function createMapping($objstring $fieldName, array $mappingData): PropertyMapping
  137.     {
  138.         if (!\array_key_exists($mappingData['mapping'], $this->mappings)) {
  139.             throw MappingNotFoundException::createNotFoundForClassAndField($mappingData['mapping'], $this->getClassName($obj), $fieldName);
  140.         }
  141.         $config $this->mappings[$mappingData['mapping']];
  142.         $fileProperty $mappingData['propertyName'] ?? $fieldName;
  143.         $fileNameProperty = empty($mappingData['fileNameProperty']) ? $fileProperty.$this->defaultFilenameAttributeSuffix $mappingData['fileNameProperty'];
  144.         $mapping = new PropertyMapping($fileProperty$fileNameProperty$mappingData);
  145.         $mapping->setMappingName($mappingData['mapping']);
  146.         $mapping->setMapping($config);
  147.         if (!empty($config['namer']) && null !== $config['namer']['service']) {
  148.             $namerConfig $config['namer'];
  149.             $namer $this->container->get($namerConfig['service']);
  150.             if (!empty($namerConfig['options'])) {
  151.                 if (!$namer instanceof ConfigurableInterface) {
  152.                     throw new \LogicException(\sprintf('Namer %s can not receive options as it does not implement ConfigurableInterface.'$namerConfig['service']));
  153.                 }
  154.                 $namer->configure($namerConfig['options']);
  155.             }
  156.             $mapping->setNamer($namer);
  157.         }
  158.         if (!empty($config['directory_namer']) && null !== $config['directory_namer']['service']) {
  159.             $namerConfig $config['directory_namer'];
  160.             $namer $this->container->get($namerConfig['service']);
  161.             if (!empty($namerConfig['options'])) {
  162.                 if (!$namer instanceof ConfigurableInterface) {
  163.                     throw new \LogicException(\sprintf('Namer %s can not receive options as it does not implement ConfigurableInterface.'$namerConfig['service']));
  164.                 }
  165.                 $namer->configure($namerConfig['options']);
  166.             }
  167.             $mapping->setDirectoryNamer($namer);
  168.         }
  169.         return $mapping;
  170.     }
  171.     /**
  172.      * Returns the className of the given object.
  173.      *
  174.      * @param object|mixed $object    The object to inspect
  175.      * @param string|null  $className User specified className
  176.      *
  177.      * @throws \RuntimeException
  178.      */
  179.     protected function getClassName($object, ?string $className null): string
  180.     {
  181.         if (null !== $className) {
  182.             return $className;
  183.         }
  184.         if (\is_object($object)) {
  185.             return ClassUtils::getClass($object);
  186.         }
  187.         throw new \RuntimeException('Impossible to determine the class name. Either specify it explicitly or give an object');
  188.     }
  189. }