IdReader::__construct()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 12
nc 4
nop 2
dl 0
loc 19
ccs 0
cts 13
cp 0
crap 20
rs 9.8666
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
/*
4
 * This file is part of Biurad opensource projects.
5
 *
6
 * @copyright 2019 Biurad Group (https://biurad.com/)
7
 * @license   https://opensource.org/licenses/BSD-3-Clause License
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace Flange\Database\Doctrine\Form\ChoiceList;
14
15
use Doctrine\Persistence\Mapping\ClassMetadata;
16
use Doctrine\Persistence\ObjectManager;
17
use Symfony\Component\Form\Exception\RuntimeException;
18
19
/**
20
 * A utility for reading object IDs.
21
 *
22
 * @author Bernhard Schussek <[email protected]>
23
 *
24
 * @internal
25
 */
26
class IdReader
27
{
28
    private ObjectManager $om;
29
    private ClassMetadata $classMetadata;
30
    private bool $singleId, $intId;
31
    private string $idField;
32
    private ?self $associationIdReader = null;
33
34
    public function __construct(ObjectManager $om, ClassMetadata $classMetadata)
35
    {
36
        $ids = $classMetadata->getIdentifierFieldNames();
37
        $idType = $classMetadata->getTypeOfField(\current($ids));
38
39
        $this->om = $om;
40
        $this->classMetadata = $classMetadata;
41
        $this->singleId = 1 === \count($ids);
42
        $this->intId = $this->singleId && \in_array($idType, ['integer', 'smallint', 'bigint'], true);
43
        $this->idField = \current($ids);
44
45
        // single field association are resolved, since the schema column could be an int
46
        if ($this->singleId && $classMetadata->hasAssociation($this->idField)) {
47
            $this->associationIdReader = new self($om, $om->getClassMetadata(
48
                $classMetadata->getAssociationTargetClass($this->idField)
0 ignored issues
show
Bug introduced by
It seems like $classMetadata->getAssoc...etClass($this->idField) can also be of type null; however, parameter $className of Doctrine\Persistence\Obj...ger::getClassMetadata() 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
                /** @scrutinizer ignore-type */ $classMetadata->getAssociationTargetClass($this->idField)
Loading history...
49
            ));
50
51
            $this->singleId = $this->associationIdReader->isSingleId();
52
            $this->intId = $this->associationIdReader->isIntId();
53
        }
54
    }
55
56
    /**
57
     * Returns whether the class has a single-column ID.
58
     */
59
    public function isSingleId(): bool
60
    {
61
        return $this->singleId;
62
    }
63
64
    /**
65
     * Returns whether the class has a single-column integer ID.
66
     */
67
    public function isIntId(): bool
68
    {
69
        return $this->intId;
70
    }
71
72
    /**
73
     * Returns the ID value for an object.
74
     *
75
     * This method assumes that the object has a single-column ID.
76
     */
77
    public function getIdValue(object $object = null): string
78
    {
79
        if (!$object) {
80
            return '';
81
        }
82
83
        if (!$this->om->contains($object)) {
84
            throw new RuntimeException(\sprintf('Entity of type "%s" passed to the choice field must be managed. Maybe you forget to persist it in the entity manager?', \get_debug_type($object)));
85
        }
86
87
        $this->om->initializeObject($object);
88
89
        $idValue = \current($this->classMetadata->getIdentifierValues($object));
90
91
        if ($this->associationIdReader) {
92
            $idValue = $this->associationIdReader->getIdValue($idValue);
93
        }
94
95
        return (string) $idValue;
96
    }
97
98
    /**
99
     * Returns the name of the ID field.
100
     *
101
     * This method assumes that the object has a single-column ID.
102
     */
103
    public function getIdField(): string
104
    {
105
        return $this->idField;
106
    }
107
}
108