<?php
namespace Vich\UploaderBundle\Metadata\Driver;
use Doctrine\Common\Annotations\Reader as AnnotationReader;
use Doctrine\Persistence\ManagerRegistry;
use Metadata\ClassMetadata as JMSClassMetadata;
use Metadata\Driver\AdvancedDriverInterface;
use Vich\UploaderBundle\Mapping\Annotation\Uploadable;
use Vich\UploaderBundle\Mapping\Annotation\UploadableField;
use Vich\UploaderBundle\Metadata\ClassMetadata;
/**
* @author Kévin Gomez <contact@kevingomez.fr>
* @author Konstantin Myakshin <koc-dp@yandex.ru>
*/
class AnnotationDriver implements AdvancedDriverInterface
{
/**
* @deprecated
*/
public const UPLOADABLE_ANNOTATION = Uploadable::class;
/**
* @deprecated
*/
public const UPLOADABLE_FIELD_ANNOTATION = UploadableField::class;
/** @var AnnotationReader|AttributeReader */
protected $reader;
/** @var ManagerRegistry[] */
private $managerRegistryList;
public function __construct(AnnotationReader $reader, array $managerRegistryList)
{
$this->reader = $reader;
$this->managerRegistryList = $managerRegistryList;
}
public function loadMetadataForClass(\ReflectionClass $class): ?JMSClassMetadata
{
if (!$this->isUploadable($class)) {
return null;
}
$classMetadata = new ClassMetadata($class->name);
$classMetadata->fileResources[] = $class->getFileName();
$classes = [];
do {
$classes[] = $class;
$class = $class->getParentClass();
} while (false !== $class);
$classes = \array_reverse($classes, false);
$properties = [];
foreach ($classes as $class) {
$properties = \array_merge($properties, $class->getProperties());
}
foreach ($properties as $property) {
$uploadableField = $this->reader->getPropertyAnnotation($property, UploadableField::class);
if (null === $uploadableField) {
continue;
}
/* @var $uploadableField UploadableField */
// TODO: try automatically determinate target fields if embeddable used
$fieldMetadata = [
'mapping' => $uploadableField->getMapping(),
'propertyName' => $property->getName(),
'fileNameProperty' => $uploadableField->getFileNameProperty(),
'size' => $uploadableField->getSize(),
'mimeType' => $uploadableField->getMimeType(),
'originalName' => $uploadableField->getOriginalName(),
'dimensions' => $uploadableField->getDimensions(),
];
// TODO: store UploadableField object instead of array
$classMetadata->fields[$property->getName()] = $fieldMetadata;
}
return $classMetadata;
}
public function getAllClassNames(): array
{
$classes = [];
$metadata = [];
foreach ($this->managerRegistryList as $managerRegisty) {
$managers = $managerRegisty->getManagers();
foreach ($managers as $manager) {
$metadata[] = $manager->getMetadataFactory()->getAllMetadata();
}
}
$metadata = \array_merge(...$metadata);
/** @var \Doctrine\Persistence\Mapping\ClassMetadata $classMeta */
foreach ($metadata as $classMeta) {
if ($this->isUploadable(new \ReflectionClass($classMeta->getName()))) {
$classes[] = $classMeta->getName();
}
}
return $classes;
}
protected function isUploadable(\ReflectionClass $class): bool
{
return null !== $this->reader->getClassAnnotation($class, Uploadable::class);
}
}