Completed
Pull Request — master (#7506)
by
unknown
12:20
created

SimpleObjectHydrator::prepare()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3.3332

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 3
nop 0
dl 0
loc 11
ccs 4
cts 6
cp 0.6667
crap 3.3332
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM\Internal\Hydration;
6
7
use Doctrine\DBAL\FetchMode;
8
use Doctrine\ORM\Mapping\ClassMetadata;
9
use Doctrine\ORM\Mapping\InheritanceType;
10
use Doctrine\ORM\Query;
11
use Exception;
12
use RuntimeException;
13
use function array_keys;
14
use function array_search;
15
use function count;
16
use function in_array;
17
use function key;
18
use function reset;
19
use function sprintf;
20
21
class SimpleObjectHydrator extends AbstractHydrator
22
{
23
    /** @var ClassMetadata */
24
    private $class;
25
26
    /**
27
     * {@inheritdoc}
28
     */
29 414
    protected function prepare()
30
    {
31 414
        if (count($this->rsm->aliasMap) !== 1) {
32
            throw new RuntimeException('Cannot use SimpleObjectHydrator with a ResultSetMapping that contains more than one object result.');
33
        }
34
35 414
        if ($this->rsm->scalarMappings) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->rsm->scalarMappings of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
36
            throw new RuntimeException('Cannot use SimpleObjectHydrator with a ResultSetMapping that contains scalar mappings.');
37
        }
38
39 414
        $this->class = $this->getClassMetadata(reset($this->rsm->aliasMap));
40 414
    }
41
42
    /**
43
     * {@inheritdoc}
44
     */
45 411
    protected function cleanup()
46
    {
47 411
        parent::cleanup();
48
49 411
        $this->uow->triggerEagerLoads();
50 411
        $this->uow->hydrationComplete();
51 411
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56 413
    protected function hydrateAllData()
57
    {
58 413
        $result = [];
59
60 413
        while ($row = $this->stmt->fetch(FetchMode::ASSOCIATIVE)) {
61 360
            $this->hydrateRowData($row, $result);
62
        }
63
64 411
        $this->em->getUnitOfWork()->triggerEagerLoads();
65
66 411
        return $result;
67
    }
68
69
    /**
70
     * {@inheritdoc}
71
     */
72 361
    protected function hydrateRowData(array $sqlResult, array &$result)
73
    {
74 361
        $entityName       = $this->class->getClassName();
75 361
        $data             = [];
76 361
        $discrColumnValue = null;
77
78
        // We need to find the correct entity class name if we have inheritance in resultset
79 361
        if ($this->class->inheritanceType !== InheritanceType::NONE) {
80 80
            $discrColumnName            = $this->platform->getSQLResultCasing(
81 80
                $this->class->discriminatorColumn->getColumnName()
82
            );
83 80
            $metaMappingDiscrColumnName = array_search($discrColumnName, $this->rsm->metaMappings);
84
85
            // Find mapped discriminator column from the result set.
86 80
            if ($metaMappingDiscrColumnName) {
87 80
                $discrColumnName = $metaMappingDiscrColumnName;
88
            }
89
90 80
            if (! isset($sqlResult[$discrColumnName])) {
91 1
                throw HydrationException::missingDiscriminatorColumn($entityName, $discrColumnName, key($this->rsm->aliasMap));
92
            }
93
94 79
            if ($sqlResult[$discrColumnName] === '') {
95
                throw HydrationException::emptyDiscriminatorValue(key($this->rsm->aliasMap));
96
            }
97
98 79
            $discrMap = $this->class->discriminatorMap;
99
100 79
            if (! isset($discrMap[$sqlResult[$discrColumnName]])) {
101 1
                throw HydrationException::invalidDiscriminatorValue($sqlResult[$discrColumnName], array_keys($discrMap));
102
            }
103
104 78
            $entityName       = $discrMap[$sqlResult[$discrColumnName]];
105 78
            $discrColumnValue = $sqlResult[$discrColumnName];
106
107 78
            unset($sqlResult[$discrColumnName]);
108
        }
109
110 359
        foreach ($sqlResult as $column => $value) {
111
            // An ObjectHydrator should be used instead of SimpleObjectHydrator
112 359
            if (isset($this->rsm->relationMap[$column])) {
113
                throw new Exception(sprintf('Unable to retrieve association information for column "%s"', $column));
114
            }
115
116 359
            $cacheKeyInfo = $this->hydrateColumnInfo($column);
117
118 359
            if (! $cacheKeyInfo) {
119 1
                continue;
120
            }
121
122
            // Check if value is null before conversion (because some types convert null to something else)
123 359
            $valueIsNull = $value === null;
124
125
            // Convert field to a valid PHP value
126 359
            if (isset($cacheKeyInfo['type'])) {
127 359
                $type  = $cacheKeyInfo['type'];
128 359
                $value = $type->convertToPHPValue($value, $this->platform);
129
            }
130
131 359
            $fieldName = $cacheKeyInfo['fieldName'];
132
133
            // Prevent overwrite in case of inherit classes using same property name (See AbstractHydrator)
134 359
            if (! isset($data[$fieldName]) || ! $valueIsNull) {
135
                // If we have inheritance in resultset, make sure the field belongs to the correct class
136 359
                if (isset($cacheKeyInfo['discriminatorValues']) && ! in_array($discrColumnValue, $cacheKeyInfo['discriminatorValues'], true)) {
137 31
                    continue;
138
                }
139
140 359
                $data[$fieldName] = $value;
141
            }
142
        }
143
144 359
        $uow    = $this->em->getUnitOfWork();
145 359
        $entity = $uow->createEntity($entityName, $data, $this->hints);
146
147 359
        $result[] = $entity;
148
149 359
        if (isset($this->hints[Query::HINT_INTERNAL_ITERATION]) && $this->hints[Query::HINT_INTERNAL_ITERATION]) {
150 1
            $this->uow->hydrationComplete();
151
        }
152 359
    }
153
}
154