Passed
Pull Request — 2.7 (#7974)
by Benjamin
06:56
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 53
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
C hydrateRowData() 0 80 17
A prepare() 0 11 3
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
use function in_array;
26
27
class SimpleObjectHydrator extends AbstractHydrator
28
{
29
    /**
30
     * @var ClassMetadata
31
     */
32
    private $class;
33
34
    /**
35
     * {@inheritdoc}
36
     */
37 464
    protected function prepare()
38
    {
39 464
        if (count($this->_rsm->aliasMap) !== 1) {
40
            throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping that contains more than one object result.");
41
        }
42
43 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...
44
            throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping that contains scalar mappings.");
45
        }
46
47 464
        $this->class = $this->getClassMetadata(reset($this->_rsm->aliasMap));
48 464
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53 461
    protected function cleanup()
54
    {
55 461
        parent::cleanup();
56
57 461
        $this->_uow->triggerEagerLoads();
58 461
        $this->_uow->hydrationComplete();
59 461
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64 463
    protected function hydrateAllData()
65
    {
66 463
        $result = [];
67
68 463
        while ($row = $this->_stmt->fetch(PDO::FETCH_ASSOC)) {
69 400
            $this->hydrateRowData($row, $result);
70
        }
71
72 461
        $this->_em->getUnitOfWork()->triggerEagerLoads();
73
74 461
        return $result;
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80 401
    protected function hydrateRowData(array $sqlResult, array &$result)
81
    {
82 401
        $entityName       = $this->class->name;
83 401
        $data             = [];
84 401
        $discrColumnValue = null;
85
86
        // We need to find the correct entity class name if we have inheritance in resultset
87 401
        if ($this->class->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) {
88 82
            $discrColumnName = $this->_platform->getSQLResultCasing($this->class->discriminatorColumn['name']);
89
90
            // Find mapped discriminator column from the result set.
91 82
            if ($metaMappingDiscrColumnName = array_search($discrColumnName, $this->_rsm->metaMappings)) {
92 82
                $discrColumnName = $metaMappingDiscrColumnName;
93
            }
94
95 82
            if ( ! isset($sqlResult[$discrColumnName])) {
96 1
                throw HydrationException::missingDiscriminatorColumn($entityName, $discrColumnName, key($this->_rsm->aliasMap));
97
            }
98
99 81
            if ($sqlResult[$discrColumnName] === '') {
100
                throw HydrationException::emptyDiscriminatorValue(key($this->_rsm->aliasMap));
101
            }
102
103 81
            $discrMap = $this->class->discriminatorMap;
104
105 81
            if ( ! isset($discrMap[$sqlResult[$discrColumnName]])) {
106 1
                throw HydrationException::invalidDiscriminatorValue($sqlResult[$discrColumnName], array_keys($discrMap));
107
            }
108
109 80
            $entityName       = $discrMap[$sqlResult[$discrColumnName]];
110 80
            $discrColumnValue = $sqlResult[$discrColumnName];
111
112 80
            unset($sqlResult[$discrColumnName]);
113
        }
114
115 399
        foreach ($sqlResult as $column => $value) {
116
            // An ObjectHydrator should be used instead of SimpleObjectHydrator
117 399
            if (isset($this->_rsm->relationMap[$column])) {
118
                throw new \Exception(sprintf('Unable to retrieve association information for column "%s"', $column));
119
            }
120
121 399
            $cacheKeyInfo = $this->hydrateColumnInfo($column);
122
123 399
            if ( ! $cacheKeyInfo) {
124 1
                continue;
125
            }
126
127
            // Check if value is null before conversion (because some types convert null to something else)
128 399
            $valueIsNull = null === $value;
129
130
            // Convert field to a valid PHP value
131 399
            if (isset($cacheKeyInfo['type'])) {
132 399
                $type  = $cacheKeyInfo['type'];
133 399
                $value = $type->convertToPHPValue($value, $this->_platform);
134
            }
135
136 399
            $fieldName = $cacheKeyInfo['fieldName'];
137
138
            // Prevent overwrite in case of inherit classes using same property name (See AbstractHydrator)
139 399
            if ( ! isset($data[$fieldName]) || ! $valueIsNull) {
140
                // If we have inheritance in resultset, make sure the field belongs to the correct class
141 399
                if (isset($cacheKeyInfo['discriminatorValues']) && ! in_array($discrColumnValue, $cacheKeyInfo['discriminatorValues'], true)) {
142 31
                    continue;
143
                }
144
145 399
                $data[$fieldName] = $value;
146
            }
147
        }
148
149 399
        if (isset($this->_hints[Query::HINT_REFRESH_ENTITY])) {
150 48
            $this->registerManaged($this->class, $this->_hints[Query::HINT_REFRESH_ENTITY], $data);
151
        }
152
153 399
        $uow    = $this->_em->getUnitOfWork();
154 399
        $entity = $uow->createEntity($entityName, $data, $this->_hints);
155
156 399
        $result[] = $entity;
157
158 399
        if (isset($this->_hints[Query::HINT_INTERNAL_ITERATION]) && $this->_hints[Query::HINT_INTERNAL_ITERATION]) {
159 1
            $this->_uow->hydrationComplete();
160
        }
161 399
    }
162
}
163