Completed
Push — master ( 56d3b9...264ef8 )
by Jared
01:47
created

Hydrator::hydrate()   F

Complexity

Conditions 22
Paths 240

Size

Total Lines 96

Duplication

Lines 35
Ratio 36.46 %

Importance

Changes 0
Metric Value
dl 35
loc 96
rs 2.8333
c 0
b 0
f 0
cc 22
nc 240
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Pulsar;
4
5
use Pulsar\Relation\Relationship;
6
7
class Hydrator
8
{
9
    /**
10
     * @property string|Model $modelClass
11
     *
12
     * @return Model[]
13
     */
14
    public static function hydrate(array $result, $modelClass, array $eagerLoaded): array
15
    {
16
        $ids = [];
17
        $eagerLoadedProperties = [];
18
        foreach ($eagerLoaded as $k) {
19
            $eagerLoadedProperties[$k] = $modelClass::definition()->get($k);
20
            $ids[$k] = [];
21
        }
22
23
        // fetch the models matching the query
24
        /** @var Model[] $models */
25
        $models = [];
26
        foreach ($result as $j => $row) {
27
            // type-cast the values because they came from the database
28
            foreach ($row as $k => &$v) {
29
                if ($property = $modelClass::definition()->get($k)) {
30
                    $v = Type::cast($property, $v);
31
                }
32
            }
33
34
            // create the model and cache the loaded values
35
            $models[] = new $modelClass($row);
36
37
            // capture any local ids for eager loading relationships
38
            foreach ($eagerLoaded as $k) {
39
                $localKey = $eagerLoadedProperties[$k]['local_key'];
40
                if (isset($row[$localKey])) {
41
                    $ids[$k][$j] = $row[$localKey];
42
                }
43
            }
44
        }
45
46
        // hydrate the eager loaded relationships
47
        foreach ($eagerLoaded as $k) {
48
            $property = $eagerLoadedProperties[$k];
49
            $relationModelClass = $property->getForeignModelClass();
50
            $type = $property->getRelationshipType();
51
52
            if (Relationship::BELONGS_TO == $type) {
53
                $relationships = self::fetchRelationships($relationModelClass, $ids[$k], $property->getForeignKey(), false);
54
55
                foreach ($ids[$k] as $j => $id) {
56
                    if (isset($relationships[$id])) {
57
                        $models[$j]->setRelation($k, $relationships[$id]);
58
                        // older style properties do not support this type of hydration
59
                        if (!$property->isPersisted()) {
60
                            $models[$j]->hydrateValue($k, $relationships[$id]);
61
                        }
62
                    }
63
                }
64
            } elseif (Relationship::HAS_ONE == $type) {
65
                $relationships = self::fetchRelationships($relationModelClass, $ids[$k], $property->getForeignKey(), false);
66
67 View Code Duplication
                foreach ($ids[$k] as $j => $id) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
68
                    if (isset($relationships[$id])) {
69
                        $models[$j]->setRelation($k, $relationships[$id]);
70
                        // older style properties do not support this type of hydration
71
                        if (!$property->isPersisted()) {
72
                            $models[$j]->hydrateValue($k, $relationships[$id]);
73
                        }
74
                    } else {
75
                        // when using has one eager loading we must
76
                        // explicitly mark the relationship as null
77
                        // for models not found during eager loading
78
                        // or else it will trigger another DB call
79
                        $models[$j]->clearRelation($k);
80
81
                        // older style properties do not support this type of hydration
82
                        if (!$property->isPersisted()) {
83
                            $models[$j]->hydrateValue($k, null);
84
                        }
85
                    }
86
                }
87
            } elseif (Relationship::HAS_MANY == $type) {
88
                $relationships = self::fetchRelationships($relationModelClass, $ids[$k], $property->getForeignKey(), true);
89
90 View Code Duplication
                foreach ($ids[$k] as $j => $id) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
91
                    if (isset($relationships[$id])) {
92
                        $models[$j]->setRelationCollection($k, $relationships[$id]);
93
                        // older style properties do not support this type of hydration
94
                        if (!$property->isPersisted()) {
95
                            $models[$j]->hydrateValue($k, $relationships[$id]);
96
                        }
97
                    } else {
98
                        $models[$j]->setRelationCollection($k, []);
99
                        // older style properties do not support this type of hydration
100
                        if (!$property->isPersisted()) {
101
                            $models[$j]->hydrateValue($k, []);
102
                        }
103
                    }
104
                }
105
            }
106
        }
107
108
        return $models;
109
    }
110
111
    /**
112
     * Hydrates the eager-loaded relationships for a given set of IDs.
113
     *
114
     * @param string $modelClass
115
     * @param bool   $multiple   when true will condense
116
     *
117
     * @return Model[]
118
     */
119
    private static function fetchRelationships($modelClass, array $ids, string $foreignKey, bool $multiple): array
120
    {
121
        $uniqueIds = array_unique($ids);
122
        if (0 === count($uniqueIds)) {
123
            return [];
124
        }
125
126
        $in = $foreignKey.' IN ('.implode(',', $uniqueIds).')';
127
        $models = $modelClass::where($in)
128
            ->first(Query::MAX_LIMIT);
129
130
        $result = [];
131
        foreach ($models as $model) {
132
            if ($multiple) {
133
                if (!isset($result[$model->$foreignKey])) {
134
                    $result[$model->$foreignKey] = [];
135
                }
136
                $result[$model->$foreignKey][] = $model;
137
            } else {
138
                $result[$model->$foreignKey] = $model;
139
            }
140
        }
141
142
        return $result;
143
    }
144
}
145