Completed
Push — 1.0 ( f45751...770e00 )
by Simonas
12:41 queued 10:12
created

Converter::assignArrayToObject()   C

Complexity

Conditions 12
Paths 22

Size

Total Lines 48
Code Lines 33

Duplication

Lines 5
Ratio 10.42 %

Importance

Changes 4
Bugs 2 Features 1
Metric Value
c 4
b 2
f 1
dl 5
loc 48
rs 5.1266
cc 12
eloc 33
nc 22
nop 3

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
/*
4
 * This file is part of the ONGR package.
5
 *
6
 * (c) NFQ Technologies UAB <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ONGR\ElasticsearchBundle\Result;
13
14
use ONGR\ElasticsearchBundle\Collection\Collection;
15
use ONGR\ElasticsearchBundle\Mapping\MetadataCollector;
16
use ONGR\ElasticsearchBundle\Service\Manager;
17
18
/**
19
 * This class converts array to document object.
20
 */
21
class Converter
22
{
23
    /**
24
     * @var MetadataCollector
25
     */
26
    private $metadataCollector;
27
28
    /**
29
     * Constructor.
30
     *
31
     * @param MetadataCollector $metadataCollector
32
     */
33
    public function __construct($metadataCollector)
34
    {
35
        $this->metadataCollector = $metadataCollector;
36
    }
37
38
    /**
39
     * Converts raw array to document.
40
     *
41
     * @param array   $rawData
42
     * @param Manager $manager
43
     *
44
     * @return object
45
     *
46
     * @throws \LogicException
47
     */
48
    public function convertToDocument($rawData, Manager $manager)
49
    {
50
        $types = $this->metadataCollector->getMappings($manager->getConfig()['mappings']);
51
52
        if (isset($types[$rawData['_type']])) {
53
            $metadata = $types[$rawData['_type']];
54
        } else {
55
            throw new \LogicException("Got document of unknown type '{$rawData['_type']}'.");
56
        }
57
58
        switch (true) {
59
            case isset($rawData['_source']):
60
                $rawData = array_merge($rawData, $rawData['_source']);
61
                break;
62
            case isset($rawData['fields']):
63
                $rawData = array_merge($rawData, $rawData['fields']);
64
                break;
65
            default:
66
                // Do nothing.
67
                break;
68
        }
69
70
        $object = $this->assignArrayToObject($rawData, new $metadata['namespace'](), $metadata['aliases']);
71
72
        return $object;
73
    }
74
75
    /**
76
     * Assigns all properties to object.
77
     *
78
     * @param array            $array
79
     * @param \ReflectionClass $object
80
     * @param array            $aliases
81
     *
82
     * @return object
83
     */
84
    public function assignArrayToObject(array $array, $object, array $aliases)
85
    {
86
        foreach ($array as $name => $value) {
87
            if (!isset($aliases[$name])) {
88
                continue;
89
            }
90
91
            if (isset($aliases[$name]['type'])) {
92
                switch ($aliases[$name]['type']) {
93
                    case 'date':
94
                        if (is_numeric($value) && (int)$value == $value) {
95
                            $time = $value;
96
                        } else {
97
                            $time = strtotime($value);
98
                        }
99
                        $value = new \DateTime();
100
                        $value->setTimestamp($time);
101
                        break;
102
                    case 'object':
103
                    case 'nested':
104
                        if ($aliases[$name]['multiple']) {
105
                            $value = new ObjectIterator($this, $value, $aliases[$name]);
106
                        } else {
107
                            if (!isset($value)) {
108
                                break;
109
                            }
110
                            $value = $this->assignArrayToObject(
111
                                $value,
112
                                new $aliases[$name]['namespace'](),
113
                                $aliases[$name]['aliases']
114
                            );
115
                        }
116
                        break;
117
                    default:
118
                        // Do nothing here. Default cas is required by our code style standard.
119
                        break;
120
                }
121
            }
122
123 View Code Duplication
            if ($aliases[$name]['propertyType'] == 'private') {
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...
124
                $object->{$aliases[$name]['methods']['setter']}($value);
125
            } else {
126
                $object->{$aliases[$name]['propertyName']} = $value;
127
            }
128
        }
129
130
        return $object;
131
    }
132
133
    /**
134
     * Converts object to an array.
135
     *
136
     * @param mixed $object
137
     * @param array $aliases
138
     * @param array $fields
139
     *
140
     * @return array
141
     */
142
    public function convertToArray($object, $aliases = [], $fields = [])
143
    {
144
        if (empty($aliases)) {
145
            $aliases = $this->getAlias($object);
146
            if (count($fields) > 0) {
147
                $aliases = array_intersect_key($aliases, array_flip($fields));
148
            }
149
        }
150
151
        $array = [];
152
153
        // Variable $name defined in client.
154
        foreach ($aliases as $name => $alias) {
155 View Code Duplication
            if ($aliases[$name]['propertyType'] == 'private') {
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...
156
                $value = $object->{$aliases[$name]['methods']['getter']}();
157
            } else {
158
                $value = $object->{$aliases[$name]['propertyName']};
159
            }
160
161
            if (isset($value)) {
162
                if (array_key_exists('aliases', $alias)) {
163
                    $new = [];
164
                    if ($alias['multiple']) {
165
                        $this->isCollection($aliases[$name]['propertyName'], $value);
166
                        foreach ($value as $item) {
167
                            $this->checkVariableType($item, [$alias['namespace']]);
168
                            $new[] = $this->convertToArray($item, $alias['aliases']);
169
                        }
170
                    } else {
171
                        $this->checkVariableType($value, [$alias['namespace']]);
172
                        $new = $this->convertToArray($value, $alias['aliases']);
173
                    }
174
                    $value = $new;
175
                }
176
177
                if ($value instanceof \DateTime) {
178
                    $value = $value->format(isset($alias['format']) ? $alias['format'] : \DateTime::ISO8601);
179
                }
180
181
                if (isset($alias['type'])) {
182
                    switch ($alias['type']) {
183 View Code Duplication
                        case 'float':
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...
184
                            if (is_array($value)) {
185
                                foreach ($value as $key => $item) {
186
                                    $value[$key] = (float)$item;
187
                                }
188
                            } else {
189
                                $value = (float)$value;
190
                            }
191
                            break;
192 View Code Duplication
                        case 'integer':
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...
193
                            if (is_array($value)) {
194
                                foreach ($value as $key => $item) {
195
                                    $value[$key] = (int)$item;
196
                                }
197
                            } else {
198
                                $value = (int)$value;
199
                            }
200
                            break;
201
                        default:
202
                            break;
203
                    }
204
                }
205
206
                $array[$name] = $value;
207
            }
208
        }
209
210
        return $array;
211
    }
212
213
    /**
214
     * Check if class matches the expected one.
215
     *
216
     * @param object $object
217
     * @param array  $expectedClasses
218
     *
219
     * @throws \InvalidArgumentException
220
     */
221
    private function checkVariableType($object, array $expectedClasses)
222
    {
223
        if (!is_object($object)) {
224
            $msg = 'Expected variable of type object, got ' . gettype($object) . ". (field isn't multiple)";
225
            throw new \InvalidArgumentException($msg);
226
        }
227
228
        $class = get_class($object);
229
        if (!in_array($class, $expectedClasses)) {
230
            throw new \InvalidArgumentException("Expected object of type {$expectedClasses[0]}, got {$class}.");
231
        }
232
    }
233
234
    /**
235
     * Check if value is instance of Collection.
236
     *
237
     * @param string $property
238
     * @param mixed  $value
239
     *
240
     * @throws \InvalidArgumentException
241
     */
242
    private function isCollection($property, $value)
243
    {
244
        if (!$value instanceof Collection) {
245
            $got = is_object($value) ? get_class($value) : gettype($value);
246
247
            throw new \InvalidArgumentException(
248
                sprintf('Value of "%s" property must be an instance of Collection, got %s.', $property, $got)
249
            );
250
        }
251
    }
252
253
    /**
254
     * Returns aliases for certain document.
255
     *
256
     * @param object $document
257
     *
258
     * @return array
259
     */
260
    private function getAlias($document)
261
    {
262
        $class = get_class($document);
263
        $documentMapping = $this->metadataCollector->getMapping($class);
264
265
        return $documentMapping['aliases'];
266
    }
267
}
268