Completed
Pull Request — 2.7 (#7974)
by Benjamin
08:15
created

SimpleObjectHydrator   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Test Coverage

Coverage 93.1%

Importance

Changes 0
Metric Value
wmc 23
eloc 54
dl 0
loc 133
ccs 54
cts 58
cp 0.931
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A hydrateAllData() 0 11 2
A cleanup() 0 6 1
A prepare() 0 11 3
C hydrateRowData() 0 80 17
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\ORM\Internal\Hydration;
21
22
use PDO;
23
use Doctrine\ORM\Mapping\ClassMetadata;
24
use Doctrine\ORM\Query;
25
26
class SimpleObjectHydrator extends AbstractHydrator
27
{
28
    /**
29
     * @var ClassMetadata
30
     */
31
    private $class;
32
33
    /**
34
     * {@inheritdoc}
35
     */
36 464
    protected function prepare()
37
    {
38 464
        if (count($this->_rsm->aliasMap) !== 1) {
39
            throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping that contains more than one object result.");
40
        }
41
42 464
        if ($this->_rsm->scalarMappings) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->_rsm->scalarMappings of type array 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...
43
            throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping that contains scalar mappings.");
44
        }
45
46 464
        $this->class = $this->getClassMetadata(reset($this->_rsm->aliasMap));
47 464
    }
48
49
    /**
50
     * {@inheritdoc}
51
     */
52 461
    protected function cleanup()
53
    {
54 461
        parent::cleanup();
55
56 461
        $this->_uow->triggerEagerLoads();
57 461
        $this->_uow->hydrationComplete();
58 461
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 463
    protected function hydrateAllData()
64
    {
65 463
        $result = [];
66
67 463
        while ($row = $this->_stmt->fetch(PDO::FETCH_ASSOC)) {
68 400
            $this->hydrateRowData($row, $result);
69
        }
70
71 461
        $this->_em->getUnitOfWork()->triggerEagerLoads();
72
73 461
        return $result;
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79 401
    protected function hydrateRowData(array $sqlResult, array &$result)
80
    {
81 401
        $entityName       = $this->class->name;
82 401
        $data             = [];
83 401
        $discrColumnValue = null;
84
85
        // We need to find the correct entity class name if we have inheritance in resultset
86 401
        if ($this->class->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) {
87 82
            $discrColumnName = $this->_platform->getSQLResultCasing($this->class->discriminatorColumn['name']);
88
89
            // Find mapped discriminator column from the result set.
90 82
            if ($metaMappingDiscrColumnName = array_search($discrColumnName, $this->_rsm->metaMappings)) {
91 82
                $discrColumnName = $metaMappingDiscrColumnName;
92
            }
93
94 82
            if ( ! isset($sqlResult[$discrColumnName])) {
95 1
                throw HydrationException::missingDiscriminatorColumn($entityName, $discrColumnName, key($this->_rsm->aliasMap));
96
            }
97
98 81
            if ($sqlResult[$discrColumnName] === '') {
99
                throw HydrationException::emptyDiscriminatorValue(key($this->_rsm->aliasMap));
100
            }
101
102 81
            $discrMap = $this->class->discriminatorMap;
103
104 81
            if ( ! isset($discrMap[$sqlResult[$discrColumnName]])) {
105 1
                throw HydrationException::invalidDiscriminatorValue($sqlResult[$discrColumnName], array_keys($discrMap));
106
            }
107
108 80
            $entityName       = $discrMap[$sqlResult[$discrColumnName]];
109 80
            $discrColumnValue = $sqlResult[$discrColumnName];
110
111 80
            unset($sqlResult[$discrColumnName]);
112
        }
113
114 399
        foreach ($sqlResult as $column => $value) {
115
            // An ObjectHydrator should be used instead of SimpleObjectHydrator
116 399
            if (isset($this->_rsm->relationMap[$column])) {
117
                throw new \Exception(sprintf('Unable to retrieve association information for column "%s"', $column));
118
            }
119
120 399
            $cacheKeyInfo = $this->hydrateColumnInfo($column);
121
122 399
            if ( ! $cacheKeyInfo) {
123 1
                continue;
124
            }
125
126
            // Check if value is null before conversion (because some types convert null to something else)
127 399
            $valueIsNull = null === $value;
128
129
            // Convert field to a valid PHP value
130 399
            if (isset($cacheKeyInfo['type'])) {
131 399
                $type  = $cacheKeyInfo['type'];
132 399
                $value = $type->convertToPHPValue($value, $this->_platform);
133
            }
134
135 399
            $fieldName = $cacheKeyInfo['fieldName'];
136
137
            // Prevent overwrite in case of inherit classes using same property name (See AbstractHydrator)
138 399
            if ( ! isset($data[$fieldName]) || ! $valueIsNull) {
139
                // If we have inheritance in resultset, make sure the field belongs to the correct class
140 399
                if (isset($cacheKeyInfo['discriminatorValues']) && ! in_array($discrColumnValue, $cacheKeyInfo['discriminatorValues'], true)) {
141 31
                    continue;
142
                }
143
144 399
                $data[$fieldName] = $value;
145
            }
146
        }
147
148 399
        if (isset($this->_hints[Query::HINT_REFRESH_ENTITY])) {
149 48
            $this->registerManaged($this->class, $this->_hints[Query::HINT_REFRESH_ENTITY], $data);
150
        }
151
152 399
        $uow    = $this->_em->getUnitOfWork();
153 399
        $entity = $uow->createEntity($entityName, $data, $this->_hints);
154
155 399
        $result[] = $entity;
156
157 399
        if (isset($this->_hints[Query::HINT_INTERNAL_ITERATION]) && $this->_hints[Query::HINT_INTERNAL_ITERATION]) {
158 1
            $this->_uow->hydrationComplete();
159
        }
160 399
    }
161
}
162