Completed
Pull Request — master (#5)
by Jacob
02:31
created

Hydrator::extractRelationship()   D

Complexity

Conditions 10
Paths 4

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 28
rs 4.8196
cc 10
eloc 17
nc 4
nop 2

How to fix   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 As3\Modlr\Persister\MongoDb;
4
5
use As3\Modlr\Metadata\EntityMetadata;
6
use As3\Modlr\Metadata\RelationshipMetadata;
7
use As3\Modlr\Persister\PersisterException;
8
use As3\Modlr\Persister\Record;
9
use As3\Modlr\Store\Store;
10
11
/**
12
 * Hydrates raw, MongoDB array results into Record instances.
13
 *
14
 * @author Jacob Bare <[email protected]>
15
 */
16
final class Hydrator
17
{
18
    /**
19
     * Extracts the model type from a raw MongoDB result.
20
     *
21
     * @param   EntityMetadata  $metadata
22
     * @param   array           $data
23
     * @return  string
24
     * @throws  PersisterException
25
     */
26
    public function extractType(EntityMetadata $metadata, array $data)
27
    {
28
        if (false === $metadata->isPolymorphic()) {
29
            return $metadata->type;
30
        }
31
        return $this->extractField(Persister::POLYMORPHIC_KEY, $data);
32
    }
33
34
    /**
35
     * Processes a raw MongoDB result and converts it into a standardized Record object.
36
     *
37
     * @param   EntityMetadata  $metadata
38
     * @param   array           $data
39
     * @param   Store           $store
40
     * @return  Record
41
     */
42
    public function hydrateOne(EntityMetadata $metadata, array $data, Store $store)
43
    {
44
        // Get the identifier and model type value from the raw result.
45
        list($identifier, $type) = $this->extractIdAndType($metadata, $data);
46
47
        // Reload the metadata in case a polymorphic type was found.
48
        $metadata = $store->getMetadataForType($type);
49
50
        // Convert relationships to the proper format.
51
        $data = $this->convertRelationships($metadata, $data);
52
53
        return new Record($type, $identifier, $data);
54
    }
55
56
    /**
57
     * Processes multiple, raw MongoDB results and converts them into an array of standardized Record objects.
58
     *
59
     * @param   EntityMetadata  $metadata
60
     * @param   array           $data
0 ignored issues
show
Bug introduced by
There is no parameter named $data. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
61
     * @param   Store           $store
62
     * @return  Record[]
63
     */
64
    public function hydrateMany(EntityMetadata $metadata, array $results, Store $store)
65
    {
66
        $records = [];
67
        foreach ($results as $data) {
68
            $records[] = $this->hydrateOne($metadata, $data, $store);
69
        }
70
        return $records;
71
    }
72
73
    /**
74
     * Converts the relationships on a raw result to the proper format.
75
     *
76
     * @param   EntityMetadata  $metadata
77
     * @param   array           &$data
78
     * @return  array
79
     */
80
    private function convertRelationships(EntityMetadata $metadata, array $data)
81
    {
82
        foreach ($metadata->getRelationships() as $key => $relMeta) {
83
            if (!isset($data[$key])) {
84
                continue;
85
            }
86
            if (true === $relMeta->isMany() && !is_array($data[$key])) {
87
                throw PersisterException::badRequest(sprintf('Relationship key "%s" is a reference many. Expected record data type of array, "%s" found on model "%s" for identifier "%s"', $key, gettype($data[$key]), $type, $identifier));
88
            }
89
            $references = $relMeta->isOne() ? [$data[$key]] : $data[$key];
90
91
            $extracted = [];
92
            foreach ($references as $reference) {
93
                $extracted[] =  $this->extractRelationship($relMeta, $reference);
94
            }
95
            $data[$key] = $relMeta->isOne() ? reset($extracted) : $extracted;
96
        }
97
        return $data;
98
    }
99
100
    /**
101
     * Extracts a root field from a raw MongoDB result.
102
     *
103
     * @param   string  $key
104
     * @param   array   $data
105
     * @return  mixed
106
     * @throws  PersisterException
107
     */
108
    private function extractField($key, array $data)
109
    {
110
        if (!isset($data[$key])) {
111
            throw PersisterException::badRequest(sprintf('Unable to extract a field value. The "%s" key was not found.', $key));
112
        }
113
        return $data[$key];
114
    }
115
116
    /**
117
     * Extracts the identifier and model type from a raw result and removes them from the source data.
118
     * Returns as a tuple.
119
     *
120
     * @param   string  $key
0 ignored issues
show
Bug introduced by
There is no parameter named $key. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
121
     * @param   array   $data
122
     * @return  array
123
     * @throws  PersisterException
124
     */
125
    private function extractIdAndType(EntityMetadata $metadata, array &$data)
126
    {
127
        $identifier = $this->extractField(Persister::IDENTIFIER_KEY, $data);
128
        unset($data[Persister::IDENTIFIER_KEY]);
129
130
        $key = Persister::POLYMORPHIC_KEY;
131
        $type = $this->extractType($metadata, $data);
132
        if (isset($data[$key])) {
133
            unset($data[$key]);
134
        }
135
        return [$identifier, $type];
136
    }
137
138
    /**
139
     * Extracts a standard relationship array that the store expects from a raw MongoDB reference value.
140
     *
141
     * @param   RelationshipMetadata    $relMeta
142
     * @param   mixed                   $reference
143
     * @return  array
144
     * @throws  RuntimeException        If the relationship could not be extracted.
145
     */
146
    private function extractRelationship(RelationshipMetadata $relMeta, $reference)
147
    {
148
        $simple  = false === $relMeta->isPolymorphic();
149
        $idKey   = Persister::IDENTIFIER_KEY;
150
        $typeKey = Persister::POLYMORPHIC_KEY;
151
152
        if (true === $simple && is_array($reference) && isset($reference[$idKey])) {
153
            return [
154
                'id'    => $reference[$idKey],
155
                'type'  => $relMeta->getEntityType(),
156
            ];
157
        }
158
159
        if (true === $simple && !is_array($reference)) {
160
            return [
161
                'id'    => $reference,
162
                'type'  => $relMeta->getEntityType(),
163
            ];
164
        }
165
166
        if (false === $simple && is_array($reference) && isset($reference[$idKey]) && isset($reference[$typeKey])) {
167
            return [
168
                'id'    => $reference[$idKey],
169
                'type'  => $reference[$typeKey],
170
            ];
171
        }
172
        throw PersisterException::badRequest('Unable to extract a reference id.');
173
    }
174
}
175