Passed
Pull Request — master (#121)
by Arnaud
02:51
created

MetadataHelper::findMetadata()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 13
rs 10
1
<?php
2
3
namespace LAG\AdminBundle\Bridge\Doctrine\ORM\Metadata;
4
5
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
6
use Doctrine\ORM\EntityManagerInterface;
7
use Doctrine\ORM\Mapping\ClassMetadataInfo;
8
use Exception;
9
use LAG\AdminBundle\Field\Definition\FieldDefinition;
10
11
class MetadataHelper implements MetadataHelperInterface
12
{
13
    /**
14
     * @var EntityManagerInterface
15
     */
16
    private $entityManager;
17
18
    public function __construct(EntityManagerInterface $entityManager)
19
    {
20
        $this->entityManager = $entityManager;
21
    }
22
23
    public function getFields(string $entityClass): array
24
    {
25
        $metadata = $this->entityManager->getClassMetadata($entityClass);
26
27
        // As the Doctrine ClassMetadata interface does not expose any properties, we should check the instance of the
28
        // returned metadata class to respect the good practices
29
        if (!$metadata instanceof ClassMetadataInfo) {
30
            return [];
31
        }
32
        $fieldNames = (array) $metadata->fieldNames;
33
        $fields = [];
34
35
        foreach ($fieldNames as $fieldName) {
36
            // Remove the primary key field if it's not managed manually
37
            if (!$metadata->isIdentifierNatural() && in_array($fieldName, $metadata->identifier)) {
38
                continue;
39
            }
40
            $mapping = $metadata->getFieldMapping($fieldName);
41
            $formOptions = [];
42
43
            // When a field is defined as nullable in the Doctrine entity configuration, the associated form field
44
            // should not be required neither
45
            if (key_exists('nullable', $mapping) && true === $mapping['nullable']) {
46
                $formOptions['required'] = false;
47
            }
48
            $fields[$fieldName] = new FieldDefinition($metadata->getTypeOfField($fieldName), [], $formOptions);
0 ignored issues
show
Bug introduced by
It seems like $metadata->getTypeOfField($fieldName) can also be of type null; however, parameter $type of LAG\AdminBundle\Field\De...finition::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

48
            $fields[$fieldName] = new FieldDefinition(/** @scrutinizer ignore-type */ $metadata->getTypeOfField($fieldName), [], $formOptions);
Loading history...
49
        }
50
51
        foreach ($metadata->associationMappings as $fieldName => $relation) {
52
            $formOptions = [];
53
            $formType = 'choice';
54
55
            if (ClassMetadataInfo::MANY_TO_MANY === $relation['type']) {
56
                $formOptions['expanded'] = true;
57
                $formOptions['multiple'] = true;
58
            }
59
            if ($this->isJoinColumnNullable($relation)) {
60
                $formOptions['required'] = false;
61
            }
62
            $fields[$fieldName] = new FieldDefinition($formType, [], $formOptions);
63
        }
64
65
        return $fields;
66
    }
67
68
    /**
69
     * Return the Doctrine metadata of the given class.
70
     *
71
     * @param $class
72
     *
73
     * @return ClassMetadata|null
74
     */
75
    public function findMetadata($class): ?ClassMetadata
76
    {
77
        $metadata = null;
78
79
        try {
80
            // We could not use the hasMetadataFor() method as it is not working if the entity is not loaded. But
81
            // the getMetadataFor() method could throw an exception if the class is not found
82
            $metadata = $this->entityManager->getMetadataFactory()->getMetadataFor($class);
83
        } catch (Exception $exception) {
84
            // If an exception is raised, nothing to do. Extra data from metadata will be not used.
85
        }
86
87
        return $metadata;
88
    }
89
90
    private function isJoinColumnNullable(array $relation)
91
    {
92
        if (!key_exists('joinColumns', $relation)) {
93
            return false;
94
        }
95
96
        if (!key_exists('nullable', $relation['joinColumns'])) {
97
            return false;
98
        }
99
100
        return false === $relation['joinColumns']['nullable'];
101
    }
102
}
103